Skip to content

Commit fc6c811

Browse files
authored
Remove dead-code in the LockFreeLinkedList implementation after new c… (#3624)
* Remove dead-code in the LockFreeLinkedList implementation after new channels implementation * Slightly speedup the build without unnecessary stress-tests * Get rid of dead-code that was used only by channels, so it's easier to reason about JobSupport implementation * Slightly cut dex size in the face of new channels regression as LFLL is no longer shared between JobSupport and Channel
1 parent 8c4ff51 commit fc6c811

File tree

10 files changed

+1
-803
lines changed

10 files changed

+1
-803
lines changed

kotlinx-coroutines-core/common/src/internal/Atomic.kt

+1-41
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,6 @@ public abstract class OpDescriptor {
2929
abstract val atomicOp: AtomicOp<*>?
3030

3131
override fun toString(): String = "$classSimpleName@$hexAddress" // debug
32-
33-
fun isEarlierThan(that: OpDescriptor): Boolean {
34-
val thisOp = atomicOp ?: return false
35-
val thatOp = that.atomicOp ?: return false
36-
return thisOp.opSequence < thatOp.opSequence
37-
}
3832
}
3933

4034
@JvmField
@@ -55,25 +49,9 @@ internal val NO_DECISION: Any = Symbol("NO_DECISION")
5549
public abstract class AtomicOp<in T> : OpDescriptor() {
5650
private val _consensus = atomic<Any?>(NO_DECISION)
5751

58-
// Returns NO_DECISION when there is not decision yet
59-
val consensus: Any? get() = _consensus.value
60-
61-
val isDecided: Boolean get() = _consensus.value !== NO_DECISION
62-
63-
/**
64-
* Sequence number of this multi-word operation for deadlock resolution.
65-
* An operation with lower number aborts itself with (using [RETRY_ATOMIC] error symbol) if it encounters
66-
* the need to help the operation with higher sequence number and then restarts
67-
* (using higher `opSequence` to ensure progress).
68-
* Simple operations that cannot get into the deadlock always return zero here.
69-
*
70-
* See https://github.com/Kotlin/kotlinx.coroutines/issues/504
71-
*/
72-
open val opSequence: Long get() = 0L
73-
7452
override val atomicOp: AtomicOp<*> get() = this
7553

76-
fun decide(decision: Any?): Any? {
54+
private fun decide(decision: Any?): Any? {
7755
assert { decision !== NO_DECISION }
7856
val current = _consensus.value
7957
if (current !== NO_DECISION) return current
@@ -98,21 +76,3 @@ public abstract class AtomicOp<in T> : OpDescriptor() {
9876
return decision
9977
}
10078
}
101-
102-
/**
103-
* A part of multi-step atomic operation [AtomicOp].
104-
*
105-
* @suppress **This is unstable API and it is subject to change.**
106-
*/
107-
public abstract class AtomicDesc {
108-
lateinit var atomicOp: AtomicOp<*> // the reference to parent atomicOp, init when AtomicOp is created
109-
abstract fun prepare(op: AtomicOp<*>): Any? // returns `null` if prepared successfully
110-
abstract fun complete(op: AtomicOp<*>, failure: Any?) // decision == null if success
111-
}
112-
113-
/**
114-
* It is returned as an error by [AtomicOp] implementations when they detect potential deadlock
115-
* using [AtomicOp.opSequence] numbers.
116-
*/
117-
@JvmField
118-
internal val RETRY_ATOMIC: Any = Symbol("RETRY_ATOMIC")

kotlinx-coroutines-core/common/src/internal/LockFreeLinkedList.common.kt

-61
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,8 @@ public expect open class LockFreeLinkedListNode() {
1616
public fun addLast(node: LockFreeLinkedListNode)
1717
public fun addOneIfEmpty(node: LockFreeLinkedListNode): Boolean
1818
public inline fun addLastIf(node: LockFreeLinkedListNode, crossinline condition: () -> Boolean): Boolean
19-
public inline fun addLastIfPrev(
20-
node: LockFreeLinkedListNode,
21-
predicate: (LockFreeLinkedListNode) -> Boolean
22-
): Boolean
23-
24-
public inline fun addLastIfPrevAndIf(
25-
node: LockFreeLinkedListNode,
26-
predicate: (LockFreeLinkedListNode) -> Boolean, // prev node predicate
27-
crossinline condition: () -> Boolean // atomically checked condition
28-
): Boolean
29-
3019
public open fun remove(): Boolean
3120

32-
/**
33-
* Helps fully finish [remove] operation, must be invoked after [remove] if needed.
34-
* Ensures that traversing the list via prev pointers sees this node as removed.
35-
* No-op on JS
36-
*/
37-
public fun helpRemove()
38-
public fun removeFirstOrNull(): LockFreeLinkedListNode?
39-
public inline fun <reified T> removeFirstIfIsInstanceOfOrPeekIf(predicate: (T) -> Boolean): T?
4021
}
4122

4223
/** @suppress **This is unstable API and it is subject to change.** */
@@ -45,45 +26,3 @@ public expect open class LockFreeLinkedListHead() : LockFreeLinkedListNode {
4526
public inline fun <reified T : LockFreeLinkedListNode> forEach(block: (T) -> Unit)
4627
public final override fun remove(): Nothing
4728
}
48-
49-
/** @suppress **This is unstable API and it is subject to change.** */
50-
public expect open class AddLastDesc<T : LockFreeLinkedListNode>(
51-
queue: LockFreeLinkedListNode,
52-
node: T
53-
) : AbstractAtomicDesc {
54-
val queue: LockFreeLinkedListNode
55-
val node: T
56-
override fun finishPrepare(prepareOp: PrepareOp)
57-
override fun finishOnSuccess(affected: LockFreeLinkedListNode, next: LockFreeLinkedListNode)
58-
}
59-
60-
/** @suppress **This is unstable API and it is subject to change.** */
61-
public expect open class RemoveFirstDesc<T>(queue: LockFreeLinkedListNode): AbstractAtomicDesc {
62-
val queue: LockFreeLinkedListNode
63-
public val result: T
64-
override fun finishPrepare(prepareOp: PrepareOp)
65-
final override fun finishOnSuccess(affected: LockFreeLinkedListNode, next: LockFreeLinkedListNode)
66-
}
67-
68-
/** @suppress **This is unstable API and it is subject to change.** */
69-
public expect abstract class AbstractAtomicDesc : AtomicDesc {
70-
final override fun prepare(op: AtomicOp<*>): Any?
71-
final override fun complete(op: AtomicOp<*>, failure: Any?)
72-
protected open fun failure(affected: LockFreeLinkedListNode): Any?
73-
protected open fun retry(affected: LockFreeLinkedListNode, next: Any): Boolean
74-
public abstract fun finishPrepare(prepareOp: PrepareOp) // non-null on failure
75-
public open fun onPrepare(prepareOp: PrepareOp): Any? // non-null on failure
76-
public open fun onRemoved(affected: LockFreeLinkedListNode) // non-null on failure
77-
protected abstract fun finishOnSuccess(affected: LockFreeLinkedListNode, next: LockFreeLinkedListNode)
78-
}
79-
80-
/** @suppress **This is unstable API and it is subject to change.** */
81-
public expect class PrepareOp: OpDescriptor {
82-
val affected: LockFreeLinkedListNode
83-
override val atomicOp: AtomicOp<*>
84-
val desc: AbstractAtomicDesc
85-
fun finishPrepare()
86-
}
87-
88-
@JvmField
89-
internal val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED")

kotlinx-coroutines-core/common/test/channels/ChannelUndeliveredElementFailureTest.kt

-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@ class ChannelUndeliveredElementFailureTest : TestBase() {
166166
fun testSendDropOldestInvokeHandlerConflated() = runTest(expected = { it is UndeliveredElementException }) {
167167
val channel = Channel<Int>(Channel.CONFLATED, onUndeliveredElement = {
168168
finish(2)
169-
println(TestException().stackTraceToString())
170169
throw TestException()
171170
})
172171
channel.send(42)

0 commit comments

Comments
 (0)