@@ -93,7 +93,15 @@ internal open class LockFreeLinkedListNode {
9393
9494 fun next (): Node = next.unwrap()
9595
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 {
97105 require(node.isFresh)
98106 condAdd?.newNode = node
99107 while (true ) { // lock-free loop on next
@@ -108,7 +116,20 @@ internal open class LockFreeLinkedListNode {
108116 }
109117 }
110118
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 {
112133 require(node.isFresh)
113134 PREV .lazySet(node, this )
114135 NEXT .lazySet(node, this )
@@ -118,15 +139,13 @@ internal open class LockFreeLinkedListNode {
118139 return true
119140 }
120141
121- fun addLastCC (node : Node , condAdd : CondAdd ? ): Boolean {
142+ // ------ addLastXXX ------
143+
144+ private fun addLastCC (node : Node , condAdd : CondAdd ? ): Boolean {
122145 require(node.isFresh)
123146 condAdd?.newNode = node
124147 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
130149 PREV .lazySet(node, prev)
131150 NEXT .lazySet(node, this )
132151 condAdd?.oldNext = this
@@ -137,20 +156,48 @@ internal open class LockFreeLinkedListNode {
137156 }
138157 }
139158
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
151178 }
152179 }
153180
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+
154201 /* *
155202 * Removes this node from the list. Returns `true` when removed successfully.
156203 */
@@ -175,6 +222,42 @@ internal open class LockFreeLinkedListNode {
175222 }
176223 }
177224
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+
178261 private fun markPrev (): Node {
179262 while (true ) { // lock-free loop on prev
180263 val prev = this .prev
@@ -276,32 +359,7 @@ internal open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
276359 }
277360 }
278361
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
305363 final override fun remove () = throw UnsupportedOperationException ()
306364
307365 fun validate () {
0 commit comments