Skip to content

Commit

Permalink
Replace nextOrClosed with nextOfIfClosed
Browse files Browse the repository at this point in the history
  • Loading branch information
ndkoval committed Apr 10, 2020
1 parent 7a77628 commit 14be936
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 19 deletions.
32 changes: 17 additions & 15 deletions kotlinx-coroutines-core/common/src/internal/ConcurrentLinkedList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ private inline fun <S : Segment<S>> S.findSegmentInternal(id: Long, createNewSeg
// uses it. This way, only one segment with each id can be added.
var cur: S = this
while (cur.id < id || cur.removed) {
val nextOrClosed = cur.nextOrClosed
if (nextOrClosed.isClosed) return SegmentOrClosed(CLOSED)
val nextNode = nextOrClosed.node
if (nextNode != null) { // there is a next node -- move there
cur = nextNode
val next = cur.nextOrIfClosed { return SegmentOrClosed(CLOSED) }
if (next != null) { // there is a next node -- move there
cur = next
continue
}
val newTail = createNewSegment(cur.id + 1, cur)
Expand Down Expand Up @@ -70,7 +68,7 @@ internal inline fun <S : Segment<S>> AtomicRef<S>.findSegmentAndMoveForward(id:
internal fun <N : ConcurrentLinkedListNode<N>> N.close(): N {
var cur: N = this
while (true) {
val next = cur.nextOrClosed.run { if (isClosed) return cur else node }
val next = cur.nextOrIfClosed { return cur }
if (next === null) {
if (cur.markAsClosed()) return cur
} else {
Expand All @@ -82,7 +80,16 @@ internal fun <N : ConcurrentLinkedListNode<N>> N.close(): N {
internal abstract class ConcurrentLinkedListNode<N : ConcurrentLinkedListNode<N>>(prev: N?) {
// Pointer to the next node, updates similarly to the Michael-Scott queue algorithm.
private val _next = atomic<Any?>(null)
val nextOrClosed: NextNodeOrClosed<N> get() = NextNodeOrClosed(_next.value)

val next: N? get() = _next.value.let { if (it === CLOSED) null else it as N? }

inline fun nextOrIfClosed(onClosedAction: () -> Unit): N? = _next.value.let {
if (it === CLOSED) {
onClosedAction()
null
} else it as N?
}

fun trySetNext(value: N): Boolean = _next.compareAndSet(null, value)

/**
Expand Down Expand Up @@ -124,7 +131,7 @@ internal abstract class ConcurrentLinkedListNode<N : ConcurrentLinkedListNode<N>
*/
fun remove() {
assert { removed } // The node should be logically removed at first.
assert { nextOrClosed.node !== null } // The physical tail cannot be removed.
assert { next !== null } // The physical tail cannot be removed.
while (true) {
// Read `next` and `prev` pointers ignoring logically removed nodes.
val prev = leftmostAliveNode
Expand All @@ -149,9 +156,9 @@ internal abstract class ConcurrentLinkedListNode<N : ConcurrentLinkedListNode<N>

private val rightmostAliveNode: N get() {
assert { !isTail } // Should not be invoked on the tail node
var cur = nextOrClosed.node!!
var cur = next!!
while (cur.removed)
cur = cur.nextOrClosed.node!!
cur = cur.next!!
return cur
}
}
Expand Down Expand Up @@ -208,11 +215,6 @@ internal inline class SegmentOrClosed<S : Segment<S>>(private val value: Any?) {
val segment: S get() = if (value === CLOSED) error("Does not contain segment") else value as S
}

internal inline class NextNodeOrClosed<N : ConcurrentLinkedListNode<N>>(private val value: Any?) {
val isClosed: Boolean get() = value === CLOSED
val node: N? get() = if (isClosed) null else value as N?
}

private const val POINTERS_SHIFT = 16

@SharedImmutable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,7 @@ internal class SegmentBasedQueue<T> {
var cur = head.value
var i = 1
while (true) {
cur = cur.nextOrClosed.run {
if (isClosed || node === null) return i
this.node!!
}
cur = cur.next ?: return i
i++
}
}
Expand Down

0 comments on commit 14be936

Please sign in to comment.