@@ -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,29 +78,30 @@ public actual open class LockFreeLinkedListNode {
11778    //  ------ addLastXXX ------
11879
11980    /* *
120-      * Adds last item to this list. 
81+      * Adds last item to this list. Returns `false` if the list is closed.  
12182     */  
122-     public  actual  fun  addLast (node :  Node )  {
83+     public  actual  fun  addLast (node :  Node ,  allowedAfterPartialClosing :   Boolean ):  Boolean  {
12384        while  (true ) { //  lock-free loop on prev.next
124-             if  (prevNode.addNext(node, this )) return 
85+             val  currentPrev =  prevNode
86+             return  when  {
87+                 currentPrev is  LIST_CLOSED_FOR_ALL  ->  false 
88+                 currentPrev is  LIST_CLOSED_FOR_SOME  -> 
89+                     allowedAfterPartialClosing &&  currentPrev.addLast(node, allowedAfterPartialClosing)
90+                 currentPrev.addNext(node, this ) ->  true 
91+                 else  ->  continue 
92+             }
12593        }
12694    }
12795
12896    /* *
129-      * Adds last item to this list atomically if the [condition] is true . 
97+      * Forbids adding some of the new items to this list . 
13098     */  
131-     public  actual  inline  fun  addLastIf (node :  Node , crossinline condition :  () ->  Boolean ): Boolean  {
132-         val  condAdd =  makeCondAddOp(node, condition)
133-         while  (true ) { //  lock-free loop on prev.next
134-             val  prev =  prevNode //  sentinel node is never removed, so prev is always defined
135-             when  (prev.tryCondAddNext(node, this , condAdd)) {
136-                 SUCCESS  ->  return  true 
137-                 FAILURE  ->  return  false 
138-             }
139-         }
140-     }
99+     public  actual  fun  closeForSome () { addLast(LIST_CLOSED_FOR_SOME (), allowedAfterPartialClosing =  false ) }
141100
142-     //  ------ addXXX util ------
101+     /* *
102+      * Forbids adding new items to this list. 
103+      */  
104+     public  actual  fun  close () { addLast(LIST_CLOSED_FOR_ALL (), allowedAfterPartialClosing =  true ) }
143105
144106    /* *
145107     * Given: 
@@ -174,17 +136,6 @@ public actual open class LockFreeLinkedListNode {
174136        return  true 
175137    }
176138
177-     //  returns UNDECIDED, SUCCESS or FAILURE
178-     @PublishedApi
179-     internal  fun  tryCondAddNext (node :  Node , next :  Node , condAdd :  CondAddOp ): Int  {
180-         node._prev .lazySet(this )
181-         node._next .lazySet(next)
182-         condAdd.oldNext =  next
183-         if  (! _next .compareAndSet(next, condAdd)) return  UNDECIDED 
184-         //  added operation successfully (linearized) -- complete it & fixup the list
185-         return  if  (condAdd.perform(this ) ==  null ) SUCCESS  else  FAILURE 
186-     }
187- 
188139    //  ------ removeXXX ------
189140
190141    /* *
@@ -284,10 +235,6 @@ public actual open class LockFreeLinkedListNode {
284235                }
285236                //  slow path when we need to help remove operations
286237                this .isRemoved ->  return  null  //  nothing to do, this node was removed, bail out asap to save time
287-                 prevNext is  OpDescriptor  ->  { //  help & retry
288-                     prevNext.perform(prev)
289-                     return  correctPrev() //  retry from scratch
290-                 }
291238                prevNext is  Removed  ->  {
292239                    if  (last != =  null ) {
293240                        //  newly added (prev) node is already removed, correct last.next around it
@@ -347,3 +294,7 @@ public actual open class LockFreeLinkedListHead : LockFreeLinkedListNode() {
347294
348295    override  fun  nextIfRemoved (): Node ?  =  null 
349296}
297+ 
298+ private  class  LIST_CLOSED_FOR_SOME : LockFreeLinkedListNode ()
299+ 
300+ private  class  LIST_CLOSED_FOR_ALL : LockFreeLinkedListNode ()
0 commit comments