Skip to content

Commit 5c582ee

Browse files
authored
Get rid of the old Kotlin/Native memory model (#3376)
* Get rid of the old Kotlin/Native memory model Fixes #3375
1 parent 007b5a5 commit 5c582ee

File tree

64 files changed

+176
-313
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+176
-313
lines changed

kotlinx-coroutines-core/build.gradle

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ void defineSourceSet(newName, dependsOn, includedInPred) {
5656
}
5757

5858
static boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } }
59+
5960
static boolean isNativeOther(String name) { return ["linux", "mingw"].any { name.startsWith(it) } }
6061

6162
defineSourceSet("concurrent", ["common"]) { it in ["jvm", "native"] }
@@ -77,39 +78,18 @@ kotlin {
7778
}
7879

7980
/*
80-
* Configure four test runs:
81-
* 1) Old memory model, Main thread
82-
* 2) New memory model, Main thread
83-
* 3) Old memory model, BG thread
84-
* 4) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
81+
* Configure two test runs:
82+
* 1) New memory model, Main thread
83+
* 2) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
8584
*
8685
* All new MM targets are build with optimize = true to have stress tests properly run.
8786
*/
8887
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests.class).configureEach {
89-
binaries {
88+
binaries.getTest("DEBUG").with {
89+
optimized = true
9090
// Test for memory leaks using a special entry point that does not exit but returns from main
91-
binaries.getTest("DEBUG").freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
92-
}
93-
94-
binaries.test("newMM", [DEBUG]) {
95-
def thisTest = it
9691
freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
97-
optimized = true
9892
binaryOptions["memoryModel"] = "experimental"
99-
testRuns.create("newMM") {
100-
setExecutionSourceFrom(thisTest)
101-
// A hack to get different suffixes in the aggregated report.
102-
executionTask.configure { targetName = "$targetName new MM" }
103-
}
104-
}
105-
106-
binaries.test("worker", [DEBUG]) {
107-
def thisTest = it
108-
freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
109-
testRuns.create("worker") {
110-
setExecutionSourceFrom(thisTest)
111-
executionTask.configure { targetName = "$targetName worker" }
112-
}
11393
}
11494

11595
binaries.test("workerWithNewMM", [DEBUG]) {
@@ -150,11 +130,11 @@ def configureNativeSourceSetPreset(name, preset) {
150130
def implementationConfiguration = configurations[hostMainCompilation.defaultSourceSet.implementationMetadataConfigurationName]
151131
// Now find the libraries: Finds platform libs & stdlib, but platform declarations are still not resolved due to IDE bugs
152132
def hostNativePlatformLibs = files(
153-
provider {
154-
implementationConfiguration.findAll {
155-
it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
133+
provider {
134+
implementationConfiguration.findAll {
135+
it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
136+
}
156137
}
157-
}
158138
)
159139
// Add all those dependencies
160140
for (suffix in sourceSetSuffixes) {

kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ import kotlinx.coroutines.internal.*
99
import kotlin.coroutines.*
1010
import kotlin.coroutines.intrinsics.*
1111
import kotlin.jvm.*
12-
import kotlin.native.concurrent.*
1312

1413
private const val UNDECIDED = 0
1514
private const val SUSPENDED = 1
1615
private const val RESUMED = 2
1716

1817
@JvmField
19-
@SharedImmutable
2018
internal val RESUME_TOKEN = Symbol("RESUME_TOKEN")
2119

2220
/**

kotlinx-coroutines-core/common/src/EventLoop.common.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import kotlinx.atomicfu.*
88
import kotlinx.coroutines.internal.*
99
import kotlin.coroutines.*
1010
import kotlin.jvm.*
11-
import kotlin.native.concurrent.*
1211

1312
/**
1413
* Extended by [CoroutineDispatcher] implementations that have event loop inside and can
@@ -123,9 +122,8 @@ internal abstract class EventLoop : CoroutineDispatcher() {
123122
open fun shutdown() {}
124123
}
125124

126-
@ThreadLocal
127125
internal object ThreadLocalEventLoop {
128-
private val ref = CommonThreadLocal<EventLoop?>()
126+
private val ref = commonThreadLocal<EventLoop?>(Symbol("ThreadLocalEventLoop"))
129127

130128
internal val eventLoop: EventLoop
131129
get() = ref.get() ?: createEventLoop().also { ref.set(it) }
@@ -142,7 +140,6 @@ internal object ThreadLocalEventLoop {
142140
}
143141
}
144142

145-
@SharedImmutable
146143
private val DISPOSED_TASK = Symbol("REMOVED_TASK")
147144

148145
// results for scheduleImpl
@@ -168,7 +165,6 @@ internal fun delayToNanos(timeMillis: Long): Long = when {
168165
internal fun delayNanosToMillis(timeNanos: Long): Long =
169166
timeNanos / MS_TO_NS
170167

171-
@SharedImmutable
172168
private val CLOSED_EMPTY = Symbol("CLOSED_EMPTY")
173169

174170
private typealias Queue<T> = LockFreeTaskQueueCore<T>

kotlinx-coroutines-core/common/src/JobSupport.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import kotlin.coroutines.*
1313
import kotlin.coroutines.intrinsics.*
1414
import kotlin.js.*
1515
import kotlin.jvm.*
16-
import kotlin.native.concurrent.*
1716

1817
/**
1918
* A concrete implementation of [Job]. It is optionally a child to a parent job.
@@ -1286,25 +1285,18 @@ internal fun Any?.unboxState(): Any? = (this as? IncompleteStateBox)?.state ?: t
12861285

12871286
// --------------- helper classes & constants for job implementation
12881287

1289-
@SharedImmutable
12901288
private val COMPLETING_ALREADY = Symbol("COMPLETING_ALREADY")
12911289
@JvmField
1292-
@SharedImmutable
12931290
internal val COMPLETING_WAITING_CHILDREN = Symbol("COMPLETING_WAITING_CHILDREN")
1294-
@SharedImmutable
12951291
private val COMPLETING_RETRY = Symbol("COMPLETING_RETRY")
1296-
@SharedImmutable
12971292
private val TOO_LATE_TO_CANCEL = Symbol("TOO_LATE_TO_CANCEL")
12981293

12991294
private const val RETRY = -1
13001295
private const val FALSE = 0
13011296
private const val TRUE = 1
13021297

1303-
@SharedImmutable
13041298
private val SEALED = Symbol("SEALED")
1305-
@SharedImmutable
13061299
private val EMPTY_NEW = Empty(false)
1307-
@SharedImmutable
13081300
private val EMPTY_ACTIVE = Empty(true)
13091301

13101302
private class Empty(override val isActive: Boolean) : Incomplete {

kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import kotlinx.coroutines.intrinsics.*
1111
import kotlinx.coroutines.selects.*
1212
import kotlin.coroutines.*
1313
import kotlin.jvm.*
14-
import kotlin.native.concurrent.*
1514

1615
/**
1716
* Abstract send channel. It is a base class for all send channel implementations.
@@ -1008,27 +1007,21 @@ internal const val RECEIVE_THROWS_ON_CLOSE = 0
10081007
internal const val RECEIVE_RESULT = 1
10091008

10101009
@JvmField
1011-
@SharedImmutable
10121010
internal val EMPTY = Symbol("EMPTY") // marker for Conflated & Buffered channels
10131011

10141012
@JvmField
1015-
@SharedImmutable
10161013
internal val OFFER_SUCCESS = Symbol("OFFER_SUCCESS")
10171014

10181015
@JvmField
1019-
@SharedImmutable
10201016
internal val OFFER_FAILED = Symbol("OFFER_FAILED")
10211017

10221018
@JvmField
1023-
@SharedImmutable
10241019
internal val POLL_FAILED = Symbol("POLL_FAILED")
10251020

10261021
@JvmField
1027-
@SharedImmutable
10281022
internal val ENQUEUE_FAILED = Symbol("ENQUEUE_FAILED")
10291023

10301024
@JvmField
1031-
@SharedImmutable
10321025
internal val HANDLER_INVOKED = Symbol("ON_CLOSE_HANDLER_INVOKED")
10331026

10341027
internal typealias Handler = (Throwable?) -> Unit

kotlinx-coroutines-core/common/src/flow/SharedFlow.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import kotlinx.coroutines.flow.internal.*
1010
import kotlinx.coroutines.internal.*
1111
import kotlin.coroutines.*
1212
import kotlin.jvm.*
13-
import kotlin.native.concurrent.*
1413

1514
/**
1615
* A _hot_ [Flow] that shares emitted values among all its collectors in a broadcast fashion, so that all collectors
@@ -710,7 +709,6 @@ internal open class SharedFlowImpl<T>(
710709
}
711710
}
712711

713-
@SharedImmutable
714712
@JvmField
715713
internal val NO_VALUE = Symbol("NO_VALUE")
716714

kotlinx-coroutines-core/common/src/flow/StateFlow.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import kotlinx.coroutines.channels.*
1010
import kotlinx.coroutines.flow.internal.*
1111
import kotlinx.coroutines.internal.*
1212
import kotlin.coroutines.*
13-
import kotlin.native.concurrent.*
1413

1514
/**
1615
* A [SharedFlow] that represents a read-only state with a single updatable data [value] that emits updates
@@ -238,10 +237,8 @@ public inline fun <T> MutableStateFlow<T>.update(function: (T) -> T) {
238237

239238
// ------------------------------------ Implementation ------------------------------------
240239

241-
@SharedImmutable
242240
private val NONE = Symbol("NONE")
243241

244-
@SharedImmutable
245242
private val PENDING = Symbol("PENDING")
246243

247244
// StateFlow slots are allocated for its collectors

kotlinx-coroutines-core/common/src/flow/internal/AbstractSharedFlow.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import kotlinx.coroutines.flow.*
99
import kotlinx.coroutines.internal.*
1010
import kotlin.coroutines.*
1111
import kotlin.jvm.*
12-
import kotlin.native.concurrent.*
1312

1413
@JvmField
15-
@SharedImmutable
1614
internal val EMPTY_RESUMES = arrayOfNulls<Continuation<Unit>?>(0)
1715

1816
internal abstract class AbstractSharedFlowSlot<F> {

kotlinx-coroutines-core/common/src/flow/internal/NullSurrogate.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,25 @@ package kotlinx.coroutines.flow.internal
66

77
import kotlinx.coroutines.internal.*
88
import kotlin.jvm.*
9-
import kotlin.native.concurrent.*
109

1110
/**
1211
* This value is used a a surrogate `null` value when needed.
1312
* It should never leak to the outside world.
1413
* Its usage typically are paired with [Symbol.unbox] usages.
1514
*/
1615
@JvmField
17-
@SharedImmutable
1816
internal val NULL = Symbol("NULL")
1917

2018
/**
2119
* Symbol to indicate that the value is not yet initialized.
2220
* It should never leak to the outside world.
2321
*/
2422
@JvmField
25-
@SharedImmutable
2623
internal val UNINITIALIZED = Symbol("UNINITIALIZED")
2724

2825
/*
2926
* Symbol used to indicate that the flow is complete.
3027
* It should never leak to the outside world.
3128
*/
3229
@JvmField
33-
@SharedImmutable
3430
internal val DONE = Symbol("DONE")

kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77

88
package kotlinx.coroutines.flow
99

10-
import kotlinx.coroutines.*
1110
import kotlinx.coroutines.flow.internal.*
1211
import kotlin.jvm.*
13-
import kotlin.native.concurrent.*
1412

1513
/**
1614
* Returns flow where all subsequent repetitions of the same value are filtered out.
@@ -45,10 +43,8 @@ public fun <T> Flow<T>.distinctUntilChanged(areEquivalent: (old: T, new: T) -> B
4543
public fun <T, K> Flow<T>.distinctUntilChangedBy(keySelector: (T) -> K): Flow<T> =
4644
distinctUntilChangedBy(keySelector = keySelector, areEquivalent = defaultAreEquivalent)
4745

48-
@SharedImmutable
4946
private val defaultKeySelector: (Any?) -> Any? = { it }
5047

51-
@SharedImmutable
5248
private val defaultAreEquivalent: (Any?, Any?) -> Boolean = { old, new -> old == new }
5349

5450
/**

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package kotlinx.coroutines.internal
88
import kotlinx.atomicfu.atomic
99
import kotlinx.coroutines.*
1010
import kotlin.jvm.*
11-
import kotlin.native.concurrent.*
1211

1312
/**
1413
* The most abstract operation that can be in process. Other threads observing an instance of this
@@ -38,7 +37,6 @@ public abstract class OpDescriptor {
3837
}
3938
}
4039

41-
@SharedImmutable
4240
@JvmField
4341
internal val NO_DECISION: Any = Symbol("NO_DECISION")
4442

@@ -117,5 +115,4 @@ public abstract class AtomicDesc {
117115
* using [AtomicOp.opSequence] numbers.
118116
*/
119117
@JvmField
120-
@SharedImmutable
121118
internal val RETRY_ATOMIC: Any = Symbol("RETRY_ATOMIC")

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package kotlinx.coroutines.internal
77
import kotlinx.atomicfu.*
88
import kotlinx.coroutines.*
99
import kotlin.jvm.*
10-
import kotlin.native.concurrent.SharedImmutable
1110

1211
/**
1312
* Returns the first segment `s` with `s.id >= id` or `CLOSED`
@@ -237,5 +236,4 @@ internal value class SegmentOrClosed<S : Segment<S>>(private val value: Any?) {
237236

238237
private const val POINTERS_SHIFT = 16
239238

240-
@SharedImmutable
241239
private val CLOSED = Symbol("CLOSED")

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ import kotlinx.atomicfu.*
88
import kotlinx.coroutines.*
99
import kotlin.coroutines.*
1010
import kotlin.jvm.*
11-
import kotlin.native.concurrent.*
1211

13-
@SharedImmutable
1412
private val UNDEFINED = Symbol("UNDEFINED")
15-
@SharedImmutable
1613
@JvmField
1714
internal val REUSABLE_CLAIMED = Symbol("REUSABLE_CLAIMED")
1815

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
package kotlinx.coroutines.internal
77

88
import kotlin.jvm.*
9-
import kotlin.native.concurrent.*
109

1110
/** @suppress **This is unstable API and it is subject to change.** */
1211
public expect open class LockFreeLinkedListNode() {
@@ -86,5 +85,4 @@ public expect class PrepareOp: OpDescriptor {
8685
}
8786

8887
@JvmField
89-
@SharedImmutable
9088
internal val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED")

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44

55
package kotlinx.coroutines.internal
66

7-
internal expect class CommonThreadLocal<T>() {
7+
internal expect class CommonThreadLocal<T> {
88
fun get(): T
99
fun set(value: T)
1010
}
11+
12+
/**
13+
* Create a thread-local storage for an object of type [T].
14+
*
15+
* If two different thread-local objects share the same [name], they will not necessarily share the same value,
16+
* but they may.
17+
* Therefore, use a unique [name] for each thread-local object.
18+
*/
19+
internal expect fun<T> commonThreadLocal(name: Symbol): CommonThreadLocal<T>

0 commit comments

Comments
 (0)