@@ -8,18 +8,6 @@ import kotlin.jvm.*
8
8
9
9
private typealias Node = LockFreeLinkedListNode
10
10
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
-
23
11
/* *
24
12
* Doubly-linked concurrent list node with remove support.
25
13
* Based on paper
@@ -49,37 +37,10 @@ public actual open class LockFreeLinkedListNode {
49
37
private fun removed (): Removed =
50
38
_removedRef .value ? : Removed (this ).also { _removedRef .lazySet(it) }
51
39
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
-
74
40
public actual open val isRemoved: Boolean get() = next is Removed
75
41
76
42
// 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
83
44
84
45
// LINEARIZABLE. Returns next non-removed Node
85
46
public actual val nextNode: Node get() =
@@ -117,20 +78,27 @@ public actual open class LockFreeLinkedListNode {
117
78
// ------ addLastXXX ------
118
79
119
80
/* *
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 .
121
82
*/
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 {
124
84
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
129
92
}
130
93
}
131
94
}
132
95
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
+ }
134
102
135
103
/* *
136
104
* Given:
@@ -165,17 +133,6 @@ public actual open class LockFreeLinkedListNode {
165
133
return true
166
134
}
167
135
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
-
179
136
// ------ removeXXX ------
180
137
181
138
/* *
@@ -273,10 +230,6 @@ public actual open class LockFreeLinkedListNode {
273
230
}
274
231
// slow path when we need to help remove operations
275
232
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
- }
280
233
prevNext is Removed -> {
281
234
if (last != = null ) {
282
235
// newly added (prev) node is already removed, correct last.next around it
@@ -332,3 +285,5 @@ public actual open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
332
285
// optimization: because head is never removed, we don't have to read _next.value to check these:
333
286
override val isRemoved: Boolean get() = false
334
287
}
288
+
289
+ private class ListClosed (@JvmField val forbiddenElementsBitmask : Int ): LockFreeLinkedListNode()
0 commit comments