1 @file:Suppress("unused", "NO_EXPLICIT_RETURN_TYPE_IN_API_MODE", "NO_EXPLICIT_VISIBILITY_IN_API_MODE") 2 3 package kotlinx.coroutines.internal 4 5 import kotlinx.coroutines.* 6 7 private typealias Node = LinkedListNode 8 9 /** @suppress **This is unstable API and it is subject to change.** */ 10 public actual typealias LockFreeLinkedListNode = LinkedListNode 11 12 /** @suppress **This is unstable API and it is subject to change.** */ 13 public actual typealias LockFreeLinkedListHead = LinkedListHead 14 15 /** @suppress **This is unstable API and it is subject to change.** */ 16 public open class LinkedListNode : DisposableHandle { 17 @PublishedApi internal var _next = this 18 @PublishedApi internal var _prev = this 19 @PublishedApi internal var _removed: Boolean = false 20 21 public inline val nextNode get() = _next 22 public inline val prevNode get() = _prev 23 public inline val isRemoved get() = _removed 24 addLastnull25 public fun addLast(node: Node) { 26 val prev = this._prev 27 node._next = this 28 node._prev = prev 29 prev._next = node 30 this._prev = node 31 } 32 33 /* 34 * Remove that is invoked as a virtual function with a 35 * potentially augmented behaviour. 36 * I.g. `LockFreeLinkedListHead` throws, while `SendElementWithUndeliveredHandler` 37 * invokes handler on remove 38 */ removenull39 public open fun remove(): Boolean { 40 return removeImpl() 41 } 42 disposenull43 override fun dispose() { 44 remove() 45 } 46 47 @PublishedApi removeImplnull48 internal fun removeImpl(): Boolean { 49 if (_removed) return false 50 val prev = this._prev 51 val next = this._next 52 prev._next = next 53 next._prev = prev 54 _removed = true 55 return true 56 } 57 addOneIfEmptynull58 public fun addOneIfEmpty(node: Node): Boolean { 59 if (_next !== this) return false 60 addLast(node) 61 return true 62 } 63 addLastIfnull64 public inline fun addLastIf(node: Node, crossinline condition: () -> Boolean): Boolean { 65 if (!condition()) return false 66 addLast(node) 67 return true 68 } 69 addLastIfPrevnull70 public inline fun addLastIfPrev(node: Node, predicate: (Node) -> Boolean): Boolean { 71 if (!predicate(_prev)) return false 72 addLast(node) 73 return true 74 } 75 addLastIfPrevAndIfnull76 public inline fun addLastIfPrevAndIf( 77 node: Node, 78 predicate: (Node) -> Boolean, // prev node predicate 79 crossinline condition: () -> Boolean // atomically checked condition 80 ): Boolean { 81 if (!predicate(_prev)) return false 82 if (!condition()) return false 83 addLast(node) 84 return true 85 } 86 helpRemovenull87 public fun helpRemove() {} // No concurrency on JS -> no removal 88 removeFirstOrNullnull89 public fun removeFirstOrNull(): Node? { 90 val next = _next 91 if (next === this) return null 92 check(next.removeImpl()) { "Should remove" } 93 return next 94 } 95 } 96 97 /** @suppress **This is unstable API and it is subject to change.** */ 98 public open class LinkedListHead : LinkedListNode() { 99 public val isEmpty get() = _next === this 100 101 /** 102 * Iterates over all elements in this list of a specified type. 103 */ forEachnull104 public inline fun <reified T : Node> forEach(block: (T) -> Unit) { 105 var cur: Node = _next 106 while (cur != this) { 107 if (cur is T) block(cur) 108 cur = cur._next 109 } 110 } 111 112 // just a defensive programming -- makes sure that list head sentinel is never removed removenull113 public final override fun remove(): Nothing = throw UnsupportedOperationException() 114 } 115