Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 10 additions & 30 deletions kotlinx-coroutines-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ void defineSourceSet(newName, dependsOn, includedInPred) {
}

static boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } }

static boolean isNativeOther(String name) { return ["linux", "mingw"].any { name.startsWith(it) } }

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

/*
* Configure four test runs:
* 1) Old memory model, Main thread
* 2) New memory model, Main thread
* 3) Old memory model, BG thread
* 4) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
* Configure two test runs:
* 1) New memory model, Main thread
* 2) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
*
* All new MM targets are build with optimize = true to have stress tests properly run.
*/
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests.class).configureEach {
binaries {
binaries.getTest("DEBUG").with {
optimized = true
// Test for memory leaks using a special entry point that does not exit but returns from main
binaries.getTest("DEBUG").freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
}

binaries.test("newMM", [DEBUG]) {
def thisTest = it
freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
optimized = true
binaryOptions["memoryModel"] = "experimental"
testRuns.create("newMM") {
setExecutionSourceFrom(thisTest)
// A hack to get different suffixes in the aggregated report.
executionTask.configure { targetName = "$targetName new MM" }
}
}

binaries.test("worker", [DEBUG]) {
def thisTest = it
freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
testRuns.create("worker") {
setExecutionSourceFrom(thisTest)
executionTask.configure { targetName = "$targetName worker" }
}
}

binaries.test("workerWithNewMM", [DEBUG]) {
Expand Down Expand Up @@ -150,11 +130,11 @@ def configureNativeSourceSetPreset(name, preset) {
def implementationConfiguration = configurations[hostMainCompilation.defaultSourceSet.implementationMetadataConfigurationName]
// Now find the libraries: Finds platform libs & stdlib, but platform declarations are still not resolved due to IDE bugs
def hostNativePlatformLibs = files(
provider {
implementationConfiguration.findAll {
it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
provider {
implementationConfiguration.findAll {
it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
}
}
}
)
// Add all those dependencies
for (suffix in sourceSetSuffixes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

private const val UNDECIDED = 0
private const val SUSPENDED = 1
private const val RESUMED = 2

@JvmField
@SharedImmutable
internal val RESUME_TOKEN = Symbol("RESUME_TOKEN")

/**
Expand Down
6 changes: 1 addition & 5 deletions kotlinx-coroutines-core/common/src/EventLoop.common.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import kotlinx.atomicfu.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

@ThreadLocal
internal object ThreadLocalEventLoop {
private val ref = CommonThreadLocal<EventLoop?>()
private val ref = commonThreadLocal<EventLoop?>(Symbol("ThreadLocalEventLoop"))

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

@SharedImmutable
private val DISPOSED_TASK = Symbol("REMOVED_TASK")

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

@SharedImmutable
private val CLOSED_EMPTY = Symbol("CLOSED_EMPTY")

private typealias Queue<T> = LockFreeTaskQueueCore<T>
Expand Down
8 changes: 0 additions & 8 deletions kotlinx-coroutines-core/common/src/JobSupport.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import kotlin.js.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

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

@SharedImmutable
private val COMPLETING_ALREADY = Symbol("COMPLETING_ALREADY")
@JvmField
@SharedImmutable
internal val COMPLETING_WAITING_CHILDREN = Symbol("COMPLETING_WAITING_CHILDREN")
@SharedImmutable
private val COMPLETING_RETRY = Symbol("COMPLETING_RETRY")
@SharedImmutable
private val TOO_LATE_TO_CANCEL = Symbol("TOO_LATE_TO_CANCEL")

private const val RETRY = -1
private const val FALSE = 0
private const val TRUE = 1

@SharedImmutable
private val SEALED = Symbol("SEALED")
@SharedImmutable
private val EMPTY_NEW = Empty(false)
@SharedImmutable
private val EMPTY_ACTIVE = Empty(true)

private class Empty(override val isActive: Boolean) : Incomplete {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import kotlinx.coroutines.intrinsics.*
import kotlinx.coroutines.selects.*
import kotlin.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

@JvmField
@SharedImmutable
internal val EMPTY = Symbol("EMPTY") // marker for Conflated & Buffered channels

@JvmField
@SharedImmutable
internal val OFFER_SUCCESS = Symbol("OFFER_SUCCESS")

@JvmField
@SharedImmutable
internal val OFFER_FAILED = Symbol("OFFER_FAILED")

@JvmField
@SharedImmutable
internal val POLL_FAILED = Symbol("POLL_FAILED")

@JvmField
@SharedImmutable
internal val ENQUEUE_FAILED = Symbol("ENQUEUE_FAILED")

@JvmField
@SharedImmutable
internal val HANDLER_INVOKED = Symbol("ON_CLOSE_HANDLER_INVOKED")

internal typealias Handler = (Throwable?) -> Unit
Expand Down
2 changes: 0 additions & 2 deletions kotlinx-coroutines-core/common/src/flow/SharedFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import kotlinx.coroutines.flow.internal.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

@SharedImmutable
@JvmField
internal val NO_VALUE = Symbol("NO_VALUE")

Expand Down
3 changes: 0 additions & 3 deletions kotlinx-coroutines-core/common/src/flow/StateFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.internal.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.native.concurrent.*

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

// ------------------------------------ Implementation ------------------------------------

@SharedImmutable
private val NONE = Symbol("NONE")

@SharedImmutable
private val PENDING = Symbol("PENDING")

// StateFlow slots are allocated for its collectors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.internal.*
import kotlin.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

@JvmField
@SharedImmutable
internal val EMPTY_RESUMES = arrayOfNulls<Continuation<Unit>?>(0)

internal abstract class AbstractSharedFlowSlot<F> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,25 @@ package kotlinx.coroutines.flow.internal

import kotlinx.coroutines.internal.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

/**
* Symbol to indicate that the value is not yet initialized.
* It should never leak to the outside world.
*/
@JvmField
@SharedImmutable
internal val UNINITIALIZED = Symbol("UNINITIALIZED")

/*
* Symbol used to indicate that the flow is complete.
* It should never leak to the outside world.
*/
@JvmField
@SharedImmutable
internal val DONE = Symbol("DONE")
4 changes: 0 additions & 4 deletions kotlinx-coroutines-core/common/src/flow/operators/Distinct.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@

package kotlinx.coroutines.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.internal.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

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

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

/**
Expand Down
3 changes: 0 additions & 3 deletions kotlinx-coroutines-core/common/src/internal/Atomic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package kotlinx.coroutines.internal
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

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

@SharedImmutable
@JvmField
internal val NO_DECISION: Any = Symbol("NO_DECISION")

Expand Down Expand Up @@ -117,5 +115,4 @@ public abstract class AtomicDesc {
* using [AtomicOp.opSequence] numbers.
*/
@JvmField
@SharedImmutable
internal val RETRY_ATOMIC: Any = Symbol("RETRY_ATOMIC")
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package kotlinx.coroutines.internal
import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.SharedImmutable

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

private const val POINTERS_SHIFT = 16

@SharedImmutable
private val CLOSED = Symbol("CLOSED")
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ import kotlinx.atomicfu.*
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.jvm.*
import kotlin.native.concurrent.*

@SharedImmutable
private val UNDEFINED = Symbol("UNDEFINED")
@SharedImmutable
@JvmField
internal val REUSABLE_CLAIMED = Symbol("REUSABLE_CLAIMED")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package kotlinx.coroutines.internal

import kotlin.jvm.*
import kotlin.native.concurrent.*

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

@JvmField
@SharedImmutable
internal val REMOVE_PREPARED: Any = Symbol("REMOVE_PREPARED")
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@

package kotlinx.coroutines.internal

internal expect class CommonThreadLocal<T>() {
internal expect class CommonThreadLocal<T> {
fun get(): T
fun set(value: T)
}

/**
* Create a thread-local storage for an object of type [T].
*
* If two different thread-local objects share the same [name], they will not necessarily share the same value,
* but they may.
* Therefore, use a unique [name] for each thread-local object.
*/
internal expect fun<T> commonThreadLocal(name: Symbol): CommonThreadLocal<T>
Loading