@@ -8,18 +8,6 @@ import kotlin.jvm.*
88
99private typealias Node = LockFreeLinkedListNode
1010
11- @PublishedApi
12- internal const val UNDECIDED : Int = 0
13-
14- @PublishedApi
15- internal const val SUCCESS : Int = 1
16-
17- @PublishedApi
18- internal const val FAILURE : Int = 2
19-
20- @PublishedApi
21- internal val CONDITION_FALSE : Any = Symbol (" CONDITION_FALSE" )
22-
2311/* *
2412 * Doubly-linked concurrent list node with remove support.
2513 * Based on paper
@@ -49,37 +37,10 @@ public actual open class LockFreeLinkedListNode {
4937 private fun removed (): Removed =
5038 _removedRef .value ? : Removed (this ).also { _removedRef .lazySet(it) }
5139
52- @PublishedApi
53- internal abstract class CondAddOp (
54- @JvmField val newNode : Node
55- ) : AtomicOp<Node>() {
56- @JvmField var oldNext: Node ? = null
57-
58- override fun complete (affected : Node , failure : Any? ) {
59- val success = failure == null
60- val update = if (success) newNode else oldNext
61- if (update != null && affected._next .compareAndSet( this , update)) {
62- // only the thread the makes this update actually finishes add operation
63- if (success) newNode.finishAdd(oldNext!! )
64- }
65- }
66- }
67-
68- @PublishedApi
69- internal inline fun makeCondAddOp (node : Node , crossinline condition : () -> Boolean ): CondAddOp =
70- object : CondAddOp (node) {
71- override fun prepare (affected : Node ): Any? = if (condition()) null else CONDITION_FALSE
72- }
73-
7440 public actual open val isRemoved: Boolean get() = next is Removed
7541
7642 // LINEARIZABLE. Returns Node | Removed
77- public val next: Any get() {
78- _next .loop { next ->
79- if (next !is OpDescriptor ) return next
80- next.perform(this )
81- }
82- }
43+ public val next: Any get() = _next .value
8344
8445 // LINEARIZABLE. Returns next non-removed Node
8546 public actual val nextNode: Node get() =
@@ -117,20 +78,27 @@ public actual open class LockFreeLinkedListNode {
11778 // ------ addLastXXX ------
11879
11980 /* *
120- * Adds last item to this list atomically if the [condition] is true .
81+ * Adds last item to this list. Returns `false` if the list is closed .
12182 */
122- public actual inline fun addLastIf (node : Node , crossinline condition : () -> Boolean ): Boolean {
123- val condAdd = makeCondAddOp(node, condition)
83+ public actual fun addLast (node : Node , permissionsBitmask : Int ): Boolean {
12484 while (true ) { // lock-free loop on prev.next
125- val prev = prevNode // sentinel node is never removed, so prev is always defined
126- when (prev.tryCondAddNext(node, this , condAdd)) {
127- SUCCESS -> return true
128- FAILURE -> return false
85+ val currentPrev = prevNode
86+ return when {
87+ currentPrev is ListClosed ->
88+ currentPrev.forbiddenElementsBitmask and permissionsBitmask == 0 &&
89+ currentPrev.addLast(node, permissionsBitmask)
90+ currentPrev.addNext(node, this ) -> true
91+ else -> continue
12992 }
13093 }
13194 }
13295
133- // ------ addXXX util ------
96+ /* *
97+ * Forbids adding new items to this list.
98+ */
99+ public actual fun close (forbiddenElementsBit : Int ) {
100+ addLast(ListClosed (forbiddenElementsBit), forbiddenElementsBit)
101+ }
134102
135103 /* *
136104 * Given:
@@ -165,17 +133,6 @@ public actual open class LockFreeLinkedListNode {
165133 return true
166134 }
167135
168- // returns UNDECIDED, SUCCESS or FAILURE
169- @PublishedApi
170- internal fun tryCondAddNext (node : Node , next : Node , condAdd : CondAddOp ): Int {
171- node._prev .lazySet(this )
172- node._next .lazySet(next)
173- condAdd.oldNext = next
174- if (! _next .compareAndSet(next, condAdd)) return UNDECIDED
175- // added operation successfully (linearized) -- complete it & fixup the list
176- return if (condAdd.perform(this ) == null ) SUCCESS else FAILURE
177- }
178-
179136 // ------ removeXXX ------
180137
181138 /* *
@@ -273,10 +230,6 @@ public actual open class LockFreeLinkedListNode {
273230 }
274231 // slow path when we need to help remove operations
275232 this .isRemoved -> return null // nothing to do, this node was removed, bail out asap to save time
276- prevNext is OpDescriptor -> { // help & retry
277- prevNext.perform(prev)
278- return correctPrev() // retry from scratch
279- }
280233 prevNext is Removed -> {
281234 if (last != = null ) {
282235 // newly added (prev) node is already removed, correct last.next around it
@@ -332,3 +285,5 @@ public actual open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
332285 // optimization: because head is never removed, we don't have to read _next.value to check these:
333286 override val isRemoved: Boolean get() = false
334287}
288+
289+ private class ListClosed (@JvmField val forbiddenElementsBitmask : Int ): LockFreeLinkedListNode()
0 commit comments