1 /*
2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_UTILITIES_FILTERQUEUE_INLINE_HPP
26 #define SHARE_UTILITIES_FILTERQUEUE_INLINE_HPP
27
28 #include "utilities/filterQueue.hpp"
29 #include "utilities/spinYield.hpp"
30
31 template <class E>
push(E data)32 void FilterQueue<E>::push(E data) {
33 Node* head;
34 Node* insnode = new Node(data);
35 SpinYield yield(SpinYield::default_spin_limit * 10); // Very unlikely with multiple failed CAS.
36 while (true){
37 head = load_first();
38 insnode->_next = head;
39 if (Atomic::cmpxchg(&_first, head, insnode) == head) {
40 break;
41 }
42 yield.wait();
43 }
44 }
45
46 // MT-Unsafe, external serialization needed.
47 template <class E>
48 template <typename MATCH_FUNC>
contains(MATCH_FUNC & match_func)49 bool FilterQueue<E>::contains(MATCH_FUNC& match_func) {
50 Node* cur = load_first();
51 if (cur == NULL) {
52 return false;
53 }
54 do {
55 if (match_func(cur->_data)) {
56 return true;
57 }
58 cur = cur->_next;
59 } while (cur != NULL);
60 return false;
61 }
62
63 // MT-Unsafe, external serialization needed.
64 template <class E>
65 template <typename MATCH_FUNC>
pop(MATCH_FUNC & match_func)66 E FilterQueue<E>::pop(MATCH_FUNC& match_func) {
67 Node* first = load_first();
68 Node* cur = first;
69 Node* prev = NULL;
70 Node* match = NULL;
71 Node* match_prev = NULL;
72
73 if (cur == NULL) {
74 return (E)NULL;
75 }
76 SpinYield yield(SpinYield::default_spin_limit * 10); // Very unlikely with multiple failed CAS.
77 do {
78 do {
79 if (match_func(cur->_data)) {
80 match = cur;
81 match_prev = prev;
82 }
83 prev = cur;
84 cur = cur->_next;
85 } while (cur != NULL);
86
87 if (match == NULL) {
88 return (E)NULL;
89 }
90
91 if (match_prev == NULL) {
92 // Working on first
93 if (Atomic::cmpxchg(&_first, match, match->_next) == match) {
94 E ret = match->_data;
95 delete match;
96 return ret;
97 }
98 yield.wait();
99 // Failed, we need to restart to know the Node prior to the match.
100 first = load_first();
101 cur = first;
102 prev = NULL;
103 match = NULL;
104 match_prev = NULL;
105 } else {
106 match_prev->_next = match->_next;
107 E ret = match->_data;
108 delete match;
109 return ret;
110 }
111 } while (true);
112 }
113
114 #endif // SHARE_UTILITIES_FILTERQUEUE_INLINE_HPP
115