You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedList.kt
+35-2Lines changed: 35 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -528,12 +528,45 @@ public open class LockFreeLinkedListNode {
528
528
privatefunmarkPrev(): Node {
529
529
_prev.loop { prev ->
530
530
if (prev isRemoved) return prev.ref
531
-
check(prev !==this) { "Cannot remove node that was not fully added" }
532
-
val removedPrev = (prev asNode).removed()
531
+
// See detailed comment in findHead on why `prev === this` is a special case for which we know that
532
+
// the prev should have being pointing to the head of list but finishAdd that was supposed
533
+
// to do that is not complete yet.
534
+
val removedPrev = (if (prev ===this) findHead() else (prev asNode)).removed()
533
535
if (_prev.compareAndSet(prev, removedPrev)) return prev
534
536
}
535
537
}
536
538
539
+
/**
540
+
* Finds the head of the list (implementing [LockFreeLinkedListHead]) by following [next] pointers.
541
+
*
542
+
* The code in [kotlinx.coroutines.experimental.JobSupport] performs upgrade of a single node to a list.
543
+
* It uses [addOneIfEmpty] to add the list head to "empty list of a single node" once.
544
+
* During upgrade a transient state of the list looks like this:
545
+
*
546
+
* ```
547
+
* +-----------------+
548
+
* | |
549
+
* node V head |
550
+
* +---+---+ +---+---+ |
551
+
* +-> | P | N | --> | P | N |-+
552
+
* | +---+---+ +---+---+
553
+
* | | ^ |
554
+
* +---- + +---------+
555
+
* ```
556
+
*
557
+
* The [prev] pointer in `node` still points to itself when [finishAdd] (invoked inside [addOneIfEmpty])
558
+
* has not completed yet. If this state is observed, then we know that [prev] should have been pointing
559
+
* to the list head. This function is looking up the head by following consistent chain of [next] pointers.
560
+
*/
561
+
privatefunfindHead(): Node {
562
+
var cur =this
563
+
while (true) {
564
+
if (cur isLockFreeLinkedListHead) return cur
565
+
cur = cur.next.unwrap()
566
+
check(cur !==this) { "Cannot loop to this while looking for list head" }
Copy file name to clipboardExpand all lines: core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobHandlersUpgradeStressTest.kt
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -55,7 +55,7 @@ class JobHandlersUpgradeStressTest : TestBase() {
0 commit comments