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