@@ -93,7 +93,15 @@ internal open class LockFreeLinkedListNode {
93
93
94
94
fun next (): Node = next.unwrap()
95
95
96
- fun addFirstCC (node : Node , condAdd : CondAdd ? ): Boolean {
96
+ fun prev (): Node {
97
+ while (true ) {
98
+ prevHelper()?.let { return it.unwrap() }
99
+ }
100
+ }
101
+
102
+ // ------ addFirstXXX ------
103
+
104
+ private fun addFirstCC (node : Node , condAdd : CondAdd ? ): Boolean {
97
105
require(node.isFresh)
98
106
condAdd?.newNode = node
99
107
while (true ) { // lock-free loop on next
@@ -108,7 +116,20 @@ internal open class LockFreeLinkedListNode {
108
116
}
109
117
}
110
118
111
- fun addIfEmpty (node : Node ): Boolean {
119
+ /* *
120
+ * Adds first item to this list.
121
+ */
122
+ fun addFirst (node : Node ) { addFirstCC(node, null ) }
123
+
124
+ /* *
125
+ * Adds first item to this list atomically if the [condition] is true.
126
+ */
127
+ inline fun addFirstIf (node : Node , crossinline condition : () -> Boolean ): Boolean =
128
+ addFirstCC(node, object : CondAdd () {
129
+ override fun isCondition (): Boolean = condition()
130
+ })
131
+
132
+ fun addFirstIfEmpty (node : Node ): Boolean {
112
133
require(node.isFresh)
113
134
PREV .lazySet(node, this )
114
135
NEXT .lazySet(node, this )
@@ -118,15 +139,13 @@ internal open class LockFreeLinkedListNode {
118
139
return true
119
140
}
120
141
121
- fun addLastCC (node : Node , condAdd : CondAdd ? ): Boolean {
142
+ // ------ addLastXXX ------
143
+
144
+ private fun addLastCC (node : Node , condAdd : CondAdd ? ): Boolean {
122
145
require(node.isFresh)
123
146
condAdd?.newNode = node
124
147
while (true ) { // lock-free loop on prev.next
125
- val prev = this .prev as Node // this sentinel node is never removed
126
- if (prev.next != = this ) {
127
- helpInsert(prev)
128
- continue
129
- }
148
+ val prev = prevHelper() ? : continue
130
149
PREV .lazySet(node, prev)
131
150
NEXT .lazySet(node, this )
132
151
condAdd?.oldNext = this
@@ -137,20 +156,48 @@ internal open class LockFreeLinkedListNode {
137
156
}
138
157
}
139
158
140
- private fun finishAdd (next : Node ) {
141
- while (true ) {
142
- val nextPrev = next.prev
143
- if (nextPrev is Removed || this .next != = next) return // next was removed, remover fixes up links
144
- if (PREV .compareAndSet(next, nextPrev, this )) {
145
- if (this .next is Removed ) {
146
- // already removed
147
- next.helpInsert(nextPrev as Node )
148
- }
149
- return
150
- }
159
+ /* *
160
+ * Adds last item to this list.
161
+ */
162
+ fun addLast (node : Node ) { addLastCC(node, null ) }
163
+
164
+ /* *
165
+ * Adds last item to this list atomically if the [condition] is true.
166
+ */
167
+ inline fun addLastIf (node : Node , crossinline condition : () -> Boolean ): Boolean =
168
+ addLastCC(node, object : CondAdd () {
169
+ override fun isCondition (): Boolean = condition()
170
+ })
171
+
172
+ inline fun addLastIfPrev (node : Node , predicate : (Node ) -> Boolean ): Boolean {
173
+ require(node.isFresh)
174
+ while (true ) { // lock-free loop on prev.next
175
+ val prev = prevHelper() ? : continue
176
+ if (! predicate(prev)) return false
177
+ if (addAfterPrev(node, prev)) return true
151
178
}
152
179
}
153
180
181
+ private fun prevHelper (): Node ? {
182
+ val prev = this .prev as Node // this sentinel node is never removed
183
+ if (prev.next == = this ) return prev
184
+ helpInsert(prev)
185
+ return null
186
+ }
187
+
188
+ private fun addAfterPrev (node : Node , prev : Node ): Boolean {
189
+ PREV .lazySet(node, prev)
190
+ NEXT .lazySet(node, this )
191
+ if (NEXT .compareAndSet(prev, this , node)) {
192
+ // added successfully (linearized add) -- fixup the list
193
+ node.finishAdd(this )
194
+ return true
195
+ }
196
+ return false
197
+ }
198
+
199
+ // ------ removeXXX ------
200
+
154
201
/* *
155
202
* Removes this node from the list. Returns `true` when removed successfully.
156
203
*/
@@ -175,6 +222,42 @@ internal open class LockFreeLinkedListNode {
175
222
}
176
223
}
177
224
225
+ inline fun <reified T > removeFirstIfIsInstanceOf (): T ? {
226
+ while (true ) { // try to linearize
227
+ val first = next()
228
+ if (first == this ) return null
229
+ if (first !is T ) return null
230
+ if (first.remove()) return first
231
+ }
232
+ }
233
+
234
+ // just peek at item when predicate is true
235
+ inline fun <reified T > removeFirstIfIsInstanceOfOrPeekIf (predicate : (T ) -> Boolean ): T ? {
236
+ while (true ) { // try to linearize
237
+ val first = next()
238
+ if (first == this ) return null
239
+ if (first !is T ) return null
240
+ if (predicate(first)) return first // just peek when predicate is true
241
+ if (first.remove()) return first
242
+ }
243
+ }
244
+
245
+ // ------ other helpers ------
246
+
247
+ private fun finishAdd (next : Node ) {
248
+ while (true ) {
249
+ val nextPrev = next.prev
250
+ if (nextPrev is Removed || this .next != = next) return // next was removed, remover fixes up links
251
+ if (PREV .compareAndSet(next, nextPrev, this )) {
252
+ if (this .next is Removed ) {
253
+ // already removed
254
+ next.helpInsert(nextPrev as Node )
255
+ }
256
+ return
257
+ }
258
+ }
259
+ }
260
+
178
261
private fun markPrev (): Node {
179
262
while (true ) { // lock-free loop on prev
180
263
val prev = this .prev
@@ -276,32 +359,7 @@ internal open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
276
359
}
277
360
}
278
361
279
- /* *
280
- * Adds first item to this list.
281
- */
282
- fun addFirst (node : Node ) { addFirstCC(node, null ) }
283
-
284
- /* *
285
- * Adds first item to this list atomically if the [condition] is true.
286
- */
287
- inline fun addFirstIf (node : Node , crossinline condition : () -> Boolean ): Boolean =
288
- addFirstCC(node, object : CondAdd () {
289
- override fun isCondition (): Boolean = condition()
290
- })
291
-
292
- /* *
293
- * Adds last item to this list.
294
- */
295
- fun addLast (node : Node ) { addLastCC(node, null ) }
296
-
297
- /* *
298
- * Adds last item to this list atomically if the [condition] is true.
299
- */
300
- inline fun addLastIf (node : Node , crossinline condition : () -> Boolean ): Boolean =
301
- addLastCC(node, object : CondAdd () {
302
- override fun isCondition (): Boolean = condition()
303
- })
304
-
362
+ // just a defensive programming -- makes sure that list head sentinel is never removed
305
363
final override fun remove () = throw UnsupportedOperationException ()
306
364
307
365
fun validate () {
0 commit comments