Skip to content

Commit 851cb9b

Browse files
author
Nikita Koval
committed
New select and Mutex implementations
see the documentation in `Select.kt` and `Mutex.kt` files for details
1 parent 3120530 commit 851cb9b

Some content is hidden

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

43 files changed

+2334
-1635
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package benchmarks.tailcall
6+
7+
import kotlinx.coroutines.*
8+
import kotlinx.coroutines.channels.*
9+
import kotlinx.coroutines.selects.*
10+
import org.openjdk.jmh.annotations.*
11+
import java.util.concurrent.*
12+
13+
@Warmup(iterations = 8, time = 1, timeUnit = TimeUnit.SECONDS)
14+
@Measurement(iterations = 8, time = 1, timeUnit = TimeUnit.SECONDS)
15+
@Fork(value = 1)
16+
@BenchmarkMode(Mode.AverageTime)
17+
@OutputTimeUnit(TimeUnit.MICROSECONDS)
18+
@State(Scope.Benchmark)
19+
open class SelectBenchmark {
20+
// 450
21+
private val iterations = 1000
22+
23+
@Benchmark
24+
fun stressSelect() = runBlocking {
25+
val pingPong = Channel<Unit>()
26+
launch {
27+
repeat(iterations) {
28+
select {
29+
pingPong.onSend(Unit) {}
30+
}
31+
}
32+
}
33+
34+
launch {
35+
repeat(iterations) {
36+
select {
37+
pingPong.onReceive() {}
38+
}
39+
}
40+
}
41+
}
42+
}

Diff for: gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ junit5_version=5.7.0
1313
atomicfu_version=0.18.2
1414
knit_version=0.4.0
1515
html_version=0.7.2
16-
lincheck_version=2.14
16+
lincheck_version=2.14.1
1717
dokka_version=1.6.21
1818
byte_buddy_version=1.10.9
1919
reactor_version=3.4.1

Diff for: kotlinx-coroutines-core/api/kotlinx-coroutines-core.api

+52-37
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,11 @@ public final class kotlinx/coroutines/JobKt {
423423
public static final fun isActive (Lkotlin/coroutines/CoroutineContext;)Z
424424
}
425425

426-
public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlinx/coroutines/Job, kotlinx/coroutines/ParentJob, kotlinx/coroutines/selects/SelectClause0 {
426+
public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlinx/coroutines/Job, kotlinx/coroutines/ParentJob {
427427
public fun <init> (Z)V
428428
protected fun afterCompletion (Ljava/lang/Object;)V
429429
public final fun attachChild (Lkotlinx/coroutines/ChildJob;)Lkotlinx/coroutines/ChildHandle;
430+
protected final fun awaitInternal (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
430431
public synthetic fun cancel ()V
431432
public synthetic fun cancel (Ljava/lang/Throwable;)Z
432433
public fun cancel (Ljava/util/concurrent/CancellationException;)V
@@ -443,6 +444,7 @@ public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlin
443444
protected final fun getCompletionCauseHandled ()Z
444445
public final fun getCompletionExceptionOrNull ()Ljava/lang/Throwable;
445446
public final fun getKey ()Lkotlin/coroutines/CoroutineContext$Key;
447+
protected final fun getOnAwaitInternal ()Lkotlinx/coroutines/selects/SelectClause1;
446448
public final fun getOnJoin ()Lkotlinx/coroutines/selects/SelectClause0;
447449
public fun getParent ()Lkotlinx/coroutines/Job;
448450
protected fun handleJobException (Ljava/lang/Throwable;)Z
@@ -462,7 +464,6 @@ public class kotlinx/coroutines/JobSupport : kotlinx/coroutines/ChildJob, kotlin
462464
public final fun parentCancelled (Lkotlinx/coroutines/ParentJob;)V
463465
public fun plus (Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
464466
public fun plus (Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/Job;
465-
public final fun registerSelectClause0 (Lkotlinx/coroutines/selects/SelectInstance;Lkotlin/jvm/functions/Function1;)V
466467
public final fun start ()Z
467468
protected final fun toCancellationException (Ljava/lang/Throwable;Ljava/lang/String;)Ljava/util/concurrent/CancellationException;
468469
public static synthetic fun toCancellationException$default (Lkotlinx/coroutines/JobSupport;Ljava/lang/Throwable;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/concurrent/CancellationException;
@@ -1194,6 +1195,11 @@ public class kotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher : kot
11941195
public fun toString ()Ljava/lang/String;
11951196
}
11961197

1198+
public final class kotlinx/coroutines/selects/OnTimeoutKt {
1199+
public static final fun onTimeout (Lkotlinx/coroutines/selects/SelectBuilder;JLkotlin/jvm/functions/Function1;)V
1200+
public static final fun onTimeout-8Mi8wO0 (Lkotlinx/coroutines/selects/SelectBuilder;JLkotlin/jvm/functions/Function1;)V
1201+
}
1202+
11971203
public abstract interface class kotlinx/coroutines/selects/SelectBuilder {
11981204
public abstract fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V
11991205
public abstract fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V
@@ -1204,71 +1210,80 @@ public abstract interface class kotlinx/coroutines/selects/SelectBuilder {
12041210

12051211
public final class kotlinx/coroutines/selects/SelectBuilder$DefaultImpls {
12061212
public static fun invoke (Lkotlinx/coroutines/selects/SelectBuilder;Lkotlinx/coroutines/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
1213+
public static fun onTimeout (Lkotlinx/coroutines/selects/SelectBuilder;JLkotlin/jvm/functions/Function1;)V
12071214
}
12081215

1209-
public final class kotlinx/coroutines/selects/SelectBuilderImpl : kotlinx/coroutines/internal/LockFreeLinkedListHead, kotlin/coroutines/Continuation, kotlin/coroutines/jvm/internal/CoroutineStackFrame, kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstance {
1216+
public final class kotlinx/coroutines/selects/SelectBuilderImpl : kotlinx/coroutines/selects/SelectImplementation {
12101217
public fun <init> (Lkotlin/coroutines/Continuation;)V
1211-
public fun disposeOnSelect (Lkotlinx/coroutines/DisposableHandle;)V
1212-
public fun getCallerFrame ()Lkotlin/coroutines/jvm/internal/CoroutineStackFrame;
1213-
public fun getCompletion ()Lkotlin/coroutines/Continuation;
1214-
public fun getContext ()Lkotlin/coroutines/CoroutineContext;
12151218
public final fun getResult ()Ljava/lang/Object;
1216-
public fun getStackTraceElement ()Ljava/lang/StackTraceElement;
12171219
public final fun handleBuilderException (Ljava/lang/Throwable;)V
1218-
public fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V
1219-
public fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V
1220-
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
1221-
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
1222-
public fun isSelected ()Z
1223-
public fun onTimeout (JLkotlin/jvm/functions/Function1;)V
1224-
public fun performAtomicTrySelect (Lkotlinx/coroutines/internal/AtomicDesc;)Ljava/lang/Object;
1225-
public fun resumeSelectWithException (Ljava/lang/Throwable;)V
1226-
public fun resumeWith (Ljava/lang/Object;)V
1227-
public fun toString ()Ljava/lang/String;
1228-
public fun trySelect ()Z
1229-
public fun trySelectOther (Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Ljava/lang/Object;
12301220
}
12311221

1232-
public abstract interface class kotlinx/coroutines/selects/SelectClause0 {
1233-
public abstract fun registerSelectClause0 (Lkotlinx/coroutines/selects/SelectInstance;Lkotlin/jvm/functions/Function1;)V
1222+
public abstract interface class kotlinx/coroutines/selects/SelectClause {
1223+
public abstract fun getClauseObject ()Ljava/lang/Object;
1224+
public abstract fun getOnCancellationConstructor ()Lkotlin/jvm/functions/Function3;
1225+
public abstract fun getProcessResFunc ()Lkotlin/jvm/functions/Function3;
1226+
public abstract fun getRegFunc ()Lkotlin/jvm/functions/Function3;
1227+
}
1228+
1229+
public abstract interface class kotlinx/coroutines/selects/SelectClause0 : kotlinx/coroutines/selects/SelectClause {
12341230
}
12351231

1236-
public abstract interface class kotlinx/coroutines/selects/SelectClause1 {
1237-
public abstract fun registerSelectClause1 (Lkotlinx/coroutines/selects/SelectInstance;Lkotlin/jvm/functions/Function2;)V
1232+
public abstract interface class kotlinx/coroutines/selects/SelectClause1 : kotlinx/coroutines/selects/SelectClause {
12381233
}
12391234

1240-
public abstract interface class kotlinx/coroutines/selects/SelectClause2 {
1241-
public abstract fun registerSelectClause2 (Lkotlinx/coroutines/selects/SelectInstance;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
1235+
public abstract interface class kotlinx/coroutines/selects/SelectClause2 : kotlinx/coroutines/selects/SelectClause {
1236+
}
1237+
1238+
public class kotlinx/coroutines/selects/SelectImplementation : kotlinx/coroutines/selects/SelectBuilder, kotlinx/coroutines/selects/SelectInstanceInternal {
1239+
public fun <init> (Lkotlin/coroutines/CoroutineContext;)V
1240+
public fun disposeOnCompletion (Lkotlinx/coroutines/DisposableHandle;)V
1241+
public fun doSelect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
1242+
public fun getContext ()Lkotlin/coroutines/CoroutineContext;
1243+
public synthetic fun invoke (Ljava/lang/Object;)Ljava/lang/Object;
1244+
public fun invoke (Ljava/lang/Throwable;)V
1245+
public fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V
1246+
public fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V
1247+
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
1248+
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
1249+
public fun onTimeout (JLkotlin/jvm/functions/Function1;)V
1250+
public fun selectInRegistrationPhase (Ljava/lang/Object;)V
1251+
public fun trySelect (Ljava/lang/Object;Ljava/lang/Object;)Z
1252+
public final fun trySelectDetailed (Ljava/lang/Object;Ljava/lang/Object;)Lkotlinx/coroutines/selects/TrySelectDetailedResult;
12421253
}
12431254

12441255
public abstract interface class kotlinx/coroutines/selects/SelectInstance {
1245-
public abstract fun disposeOnSelect (Lkotlinx/coroutines/DisposableHandle;)V
1246-
public abstract fun getCompletion ()Lkotlin/coroutines/Continuation;
1247-
public abstract fun isSelected ()Z
1248-
public abstract fun performAtomicTrySelect (Lkotlinx/coroutines/internal/AtomicDesc;)Ljava/lang/Object;
1249-
public abstract fun resumeSelectWithException (Ljava/lang/Throwable;)V
1250-
public abstract fun trySelect ()Z
1251-
public abstract fun trySelectOther (Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Ljava/lang/Object;
1256+
public abstract fun disposeOnCompletion (Lkotlinx/coroutines/DisposableHandle;)V
1257+
public abstract fun getContext ()Lkotlin/coroutines/CoroutineContext;
1258+
public abstract fun selectInRegistrationPhase (Ljava/lang/Object;)V
1259+
public abstract fun trySelect (Ljava/lang/Object;Ljava/lang/Object;)Z
12521260
}
12531261

12541262
public final class kotlinx/coroutines/selects/SelectKt {
1255-
public static final fun onTimeout-8Mi8wO0 (Lkotlinx/coroutines/selects/SelectBuilder;JLkotlin/jvm/functions/Function1;)V
12561263
public static final fun select (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
12571264
}
12581265

1266+
public final class kotlinx/coroutines/selects/SelectOldKt {
1267+
public static final fun selectOld (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
1268+
public static final fun selectUnbiasedOld (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
1269+
}
1270+
12591271
public final class kotlinx/coroutines/selects/SelectUnbiasedKt {
12601272
public static final fun selectUnbiased (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
12611273
}
12621274

1263-
public final class kotlinx/coroutines/selects/UnbiasedSelectBuilderImpl : kotlinx/coroutines/selects/SelectBuilder {
1275+
public final class kotlinx/coroutines/selects/UnbiasedSelectBuilderImpl : kotlinx/coroutines/selects/UnbiasedSelectImplementation {
12641276
public fun <init> (Lkotlin/coroutines/Continuation;)V
12651277
public final fun handleBuilderException (Ljava/lang/Throwable;)V
12661278
public final fun initSelectResult ()Ljava/lang/Object;
1279+
}
1280+
1281+
public class kotlinx/coroutines/selects/UnbiasedSelectImplementation : kotlinx/coroutines/selects/SelectImplementation {
1282+
public fun <init> (Lkotlin/coroutines/CoroutineContext;)V
1283+
public fun doSelect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
12671284
public fun invoke (Lkotlinx/coroutines/selects/SelectClause0;Lkotlin/jvm/functions/Function1;)V
12681285
public fun invoke (Lkotlinx/coroutines/selects/SelectClause1;Lkotlin/jvm/functions/Function2;)V
12691286
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
1270-
public fun invoke (Lkotlinx/coroutines/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
1271-
public fun onTimeout (JLkotlin/jvm/functions/Function1;)V
12721287
}
12731288

12741289
public final class kotlinx/coroutines/selects/WhileSelectKt {

Diff for: kotlinx-coroutines-core/common/src/Builders.common.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,10 @@ public fun <T> CoroutineScope.async(
9696
private open class DeferredCoroutine<T>(
9797
parentContext: CoroutineContext,
9898
active: Boolean
99-
) : AbstractCoroutine<T>(parentContext, true, active = active), Deferred<T>, SelectClause1<T> {
99+
) : AbstractCoroutine<T>(parentContext, true, active = active), Deferred<T> {
100100
override fun getCompleted(): T = getCompletedInternal() as T
101101
override suspend fun await(): T = awaitInternal() as T
102-
override val onAwait: SelectClause1<T> get() = this
103-
override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
104-
registerSelectClause1Internal(select, block)
102+
override val onAwait: SelectClause1<T> get() = onAwaitInternal as SelectClause1<T>
105103
}
106104

107105
private class LazyDeferredCoroutine<T>(

Diff for: kotlinx-coroutines-core/common/src/CompletableDeferred.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,12 @@ public fun <T> CompletableDeferred(value: T): CompletableDeferred<T> = Completab
7979
@Suppress("UNCHECKED_CAST")
8080
private class CompletableDeferredImpl<T>(
8181
parent: Job?
82-
) : JobSupport(true), CompletableDeferred<T>, SelectClause1<T> {
82+
) : JobSupport(true), CompletableDeferred<T> {
8383
init { initParentJob(parent) }
8484
override val onCancelComplete get() = true
8585
override fun getCompleted(): T = getCompletedInternal() as T
8686
override suspend fun await(): T = awaitInternal() as T
87-
override val onAwait: SelectClause1<T> get() = this
88-
override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
89-
registerSelectClause1Internal(select, block)
87+
override val onAwait: SelectClause1<T> get() = onAwaitInternal as SelectClause1<T>
9088

9189
override fun complete(value: T): Boolean =
9290
makeCompleting(value)

0 commit comments

Comments
 (0)