Skip to content

Commit c0d559b

Browse files
committed
DefaultDispatcher is introduced
1 parent 8552f0e commit c0d559b

File tree

16 files changed

+193
-96
lines changed

16 files changed

+193
-96
lines changed

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
2828
* Launches new coroutine without blocking current thread and returns a reference to the coroutine as a [Job].
2929
* The coroutine is cancelled when the resulting job is [cancelled][Job.cancel].
3030
*
31-
* The [context] for the new coroutine must be explicitly specified.
32-
* See [CoroutineDispatcher] for the standard [context] implementations that are provided by `kotlinx.coroutines`.
31+
* The [context] for the new coroutine can be explicitly specified.
32+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
3333
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
3434
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
35+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
3536
*
3637
* By default, the coroutine is immediately scheduled for execution.
3738
* Other options can be specified via `start` parameter. See [CoroutineStart] for details.
@@ -45,12 +46,12 @@ import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
4546
*
4647
* See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
4748
48-
* @param context context of the coroutine
49-
* @param start coroutine start option
50-
* @param block the coroutine code
49+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
50+
* @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
51+
* @param block the coroutine code.
5152
*/
5253
public fun launch(
53-
context: CoroutineContext,
54+
context: CoroutineContext = DefaultDispatcher,
5455
start: CoroutineStart = CoroutineStart.DEFAULT,
5556
block: suspend CoroutineScope.() -> Unit
5657
): Job {
@@ -137,6 +138,9 @@ public suspend fun <T> run(context: CoroutineContext, block: suspend () -> T): T
137138
* this `runBlocking` invocation throws [InterruptedException].
138139
*
139140
* See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
141+
*
142+
* @param context context of the coroutine. The default value is an implementation of [EventLoop].
143+
* @param block the coroutine code.
140144
*/
141145
@Throws(InterruptedException::class)
142146
public fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T {

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineContext.kt

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package kotlinx.coroutines.experimental
1818

1919
import java.util.concurrent.atomic.AtomicLong
2020
import kotlin.coroutines.experimental.AbstractCoroutineContextElement
21+
import kotlin.coroutines.experimental.ContinuationInterceptor
2122
import kotlin.coroutines.experimental.CoroutineContext
2223

2324
private const val DEBUG_PROPERTY_NAME = "kotlinx.coroutines.debug"
@@ -65,7 +66,16 @@ public object Unconfined : CoroutineDispatcher() {
6566
public typealias Here = Unconfined
6667

6768
/**
68-
* Creates context for the new coroutine with optional support for debugging facilities (when turned on).
69+
* This is the default [CoroutineDispatcher] that is used by all standard builders like
70+
* [launch], [async], etc if no dispatcher nor any other [ContinuationInterceptor] is specified in their context.
71+
*
72+
* It is currently equal to [CommonPool], but the value is subject to change in the future.
73+
*/
74+
public val DefaultDispatcher: CoroutineDispatcher = CommonPool
75+
76+
/**
77+
* Creates context for the new coroutine. It installs [DefaultDispatcher] when no other dispatcher nor
78+
* [ContinuationInterceptor] is specified, and adds optional support for debugging facilities (when turned on).
6979
*
7080
* **Debugging facilities:** In debug mode every coroutine is assigned a unique consecutive identifier.
7181
* Every thread that executes a coroutine has its name modified to include the name and identifier of the
@@ -82,8 +92,11 @@ public typealias Here = Unconfined
8292
* Coroutine name can be explicitly assigned using [CoroutineName] context element.
8393
* The string "coroutine" is used as a default name.
8494
*/
85-
public fun newCoroutineContext(context: CoroutineContext): CoroutineContext =
86-
if (DEBUG) context + CoroutineId(COROUTINE_ID.incrementAndGet()) else context
95+
public fun newCoroutineContext(context: CoroutineContext): CoroutineContext {
96+
val debug = if (DEBUG) context + CoroutineId(COROUTINE_ID.incrementAndGet()) else context
97+
return if (context !== DefaultDispatcher && context[ContinuationInterceptor] == null)
98+
debug + DefaultDispatcher else debug
99+
}
87100

88101
/**
89102
* Executes a block using a given coroutine context.

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineDispatcher.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import kotlin.coroutines.experimental.CoroutineContext
3030
* The coroutine will resume in whatever thread that is used by the
3131
* corresponding suspending function, without confining it to any specific thread or pool.
3232
* This in an appropriate choice for IO-intensive coroutines that do not consume CPU resources.
33+
* * [DefaultDispatcher] -- is used by all standard builder if no dispatcher nor any other [ContinuationInterceptor]
34+
* is specified in their context. It is currently equal to [CommonPool] (subject to change).
3335
* * [CommonPool] -- immediately returns from the coroutine builder and schedules coroutine execution to
3436
* a common pool of shared background threads.
3537
* This is an appropriate choice for compute-intensive coroutines that consume a lot of CPU resources.

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package kotlinx.coroutines.experimental
1818

1919
import kotlinx.coroutines.experimental.selects.SelectClause1
2020
import kotlinx.coroutines.experimental.selects.select
21+
import kotlin.coroutines.experimental.ContinuationInterceptor
2122
import kotlin.coroutines.experimental.CoroutineContext
2223

2324
/**
@@ -137,23 +138,25 @@ public interface Deferred<out T> : Job {
137138
* Creates new coroutine and returns its future result as an implementation of [Deferred].
138139
*
139140
* The running coroutine is cancelled when the resulting object is [cancelled][Job.cancel].
140-
* The [context] for the new coroutine must be explicitly specified.
141-
* See [CoroutineDispatcher] for the standard [context] implementations that are provided by `kotlinx.coroutines`.
141+
*
142+
* The [context] for the new coroutine can be explicitly specified.
143+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
142144
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
143145
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
146+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
144147
*
145148
* By default, the coroutine is immediately scheduled for execution.
146149
* Other options can be specified via `start` parameter. See [CoroutineStart] for details.
147150
* An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,,
148151
* the resulting [Deferred] is created in _new_ state. It can be explicitly started with [start][Job.start]
149152
* function and will be started implicitly on the first invocation of [join][Job.join] or [await][Deferred.await].
150153
*
151-
* @param context context of the coroutine
152-
* @param start coroutine start option
153-
* @param block the coroutine code
154+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
155+
* @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
156+
* @param block the coroutine code.
154157
*/
155158
public fun <T> async(
156-
context: CoroutineContext,
159+
context: CoroutineContext = DefaultDispatcher,
157160
start: CoroutineStart = CoroutineStart.DEFAULT,
158161
block: suspend CoroutineScope.() -> T
159162
): Deferred<T> {

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Produce.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616

1717
package kotlinx.coroutines.experimental.channels
1818

19-
import kotlinx.coroutines.experimental.CoroutineDispatcher
20-
import kotlinx.coroutines.experimental.CoroutineScope
21-
import kotlinx.coroutines.experimental.Job
22-
import kotlinx.coroutines.experimental.newCoroutineContext
19+
import kotlinx.coroutines.experimental.*
20+
import kotlin.coroutines.experimental.ContinuationInterceptor
2321
import kotlin.coroutines.experimental.CoroutineContext
2422
import kotlin.coroutines.experimental.startCoroutine
2523

@@ -72,22 +70,23 @@ typealias ChannelJob<E> = ProducerJob<E>
7270
* when the coroutine completes.
7371
* The running coroutine is cancelled when the its job is [cancelled][Job.cancel].
7472
*
75-
* The [context] for the new coroutine must be explicitly specified.
76-
* See [CoroutineDispatcher] for the standard [context] implementations that are provided by `kotlinx.coroutines`.
73+
* The [context] for the new coroutine can be explicitly specified.
74+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
7775
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
7876
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
77+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
7978
*
8079
* Uncaught exceptions in this coroutine close the channel with this exception as a cause and
8180
* the resulting channel becomes _failed_, so that any attempt to receive from such a channel throws exception.
8281
*
8382
* See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
8483
*
85-
* @param context context of the coroutine
86-
* @param capacity capacity of the channel's buffer (no buffer by default)
87-
* @param block the coroutine code
84+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
85+
* @param capacity capacity of the channel's buffer (no buffer by default).
86+
* @param block the coroutine code.
8887
*/
8988
public fun <E> produce(
90-
context: CoroutineContext,
89+
context: CoroutineContext = DefaultDispatcher,
9190
capacity: Int = 0,
9291
block: suspend ProducerScope<E>.() -> Unit
9392
): ProducerJob<E> {

integration/kotlinx-coroutines-guava/src/main/kotlin/kotlinx/coroutines/experimental/guava/ListenableFuture.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,20 @@ import com.google.common.util.concurrent.Futures
2222
import com.google.common.util.concurrent.ListenableFuture
2323
import kotlinx.coroutines.experimental.*
2424
import kotlin.coroutines.experimental.Continuation
25+
import kotlin.coroutines.experimental.ContinuationInterceptor
2526
import kotlin.coroutines.experimental.CoroutineContext
2627

2728
/**
2829
* Starts new coroutine and returns its results an an implementation of [ListenableFuture].
2930
* This coroutine builder uses [CommonPool] context by default.
3031
*
3132
* The running coroutine is cancelled when the resulting future is cancelled or otherwise completed.
32-
* If the [context] for the new coroutine is omitted or is explicitly specified but does not include a
33-
* coroutine interceptor, then [CommonPool] is used.
34-
* See [CoroutineDispatcher] for other standard [context] implementations that are provided by `kotlinx.coroutines`.
33+
*
34+
* The [context] for the new coroutine can be explicitly specified.
35+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
3536
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
3637
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
38+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
3739
*
3840
* By default, the coroutine is immediately scheduled for execution.
3941
* Other options can be specified via `start` parameter. See [CoroutineStart] for details.
@@ -43,17 +45,17 @@ import kotlin.coroutines.experimental.CoroutineContext
4345
*
4446
* See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
4547
*
46-
* @param context context of the coroutine
47-
* @param start coroutine start option
48-
* @param block the coroutine code
48+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
49+
* @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
50+
* @param block the coroutine code.
4951
*/
5052
public fun <T> future(
51-
context: CoroutineContext = CommonPool,
53+
context: CoroutineContext = DefaultDispatcher,
5254
start: CoroutineStart = CoroutineStart.DEFAULT,
5355
block: suspend CoroutineScope.() -> T
5456
): ListenableFuture<T> {
5557
require(!start.isLazy) { "$start start is not supported" }
56-
val newContext = newCoroutineContext(CommonPool + context)
58+
val newContext = newCoroutineContext(context)
5759
val job = Job(newContext[Job])
5860
val future = ListenableFutureCoroutine<T>(newContext + job)
5961
job.cancelFutureOnCompletion(future)

integration/kotlinx-coroutines-jdk8/src/main/kotlin/kotlinx/coroutines/experimental/future/Future.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import java.util.concurrent.CompletionStage
2222
import java.util.concurrent.ExecutionException
2323
import java.util.function.BiConsumer
2424
import kotlin.coroutines.experimental.Continuation
25+
import kotlin.coroutines.experimental.ContinuationInterceptor
2526
import kotlin.coroutines.experimental.CoroutineContext
2627
import kotlin.coroutines.experimental.suspendCoroutine
2728

@@ -30,11 +31,12 @@ import kotlin.coroutines.experimental.suspendCoroutine
3031
* This coroutine builder uses [CommonPool] context by default and is conceptually similar to [CompletableFuture.supplyAsync].
3132
*
3233
* The running coroutine is cancelled when the resulting future is cancelled or otherwise completed.
33-
* If the [context] for the new coroutine is omitted or is explicitly specified but does not include a
34-
* coroutine interceptor, then [CommonPool] is used.
35-
* See [CoroutineDispatcher] for other standard [context] implementations that are provided by `kotlinx.coroutines`.
34+
*
35+
* The [context] for the new coroutine can be explicitly specified.
36+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
3637
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
3738
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
39+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
3840
*
3941
* By default, the coroutine is immediately scheduled for execution.
4042
* Other options can be specified via `start` parameter. See [CoroutineStart] for details.
@@ -44,17 +46,17 @@ import kotlin.coroutines.experimental.suspendCoroutine
4446
*
4547
* See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
4648
*
47-
* @param context context of the coroutine
48-
* @param start coroutine start option
49-
* @param block the coroutine code
49+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
50+
* @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
51+
* @param block the coroutine code.
5052
*/
5153
public fun <T> future(
52-
context: CoroutineContext = CommonPool,
54+
context: CoroutineContext = DefaultDispatcher,
5355
start: CoroutineStart = CoroutineStart.DEFAULT,
5456
block: suspend CoroutineScope.() -> T
5557
): CompletableFuture<T> {
5658
require(!start.isLazy) { "$start start is not supported" }
57-
val newContext = newCoroutineContext(CommonPool + context)
59+
val newContext = newCoroutineContext(context)
5860
val job = Job(newContext[Job])
5961
val future = CompletableFutureCoroutine<T>(newContext + job)
6062
job.cancelFutureOnCompletion(future)

reactive/kotlinx-coroutines-reactive/src/main/kotlin/kotlinx/coroutines/experimental/reactive/Publish.kt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,22 @@
1717
package kotlinx.coroutines.experimental.reactive
1818

1919
import kotlinx.atomicfu.atomic
20-
import kotlinx.coroutines.experimental.AbstractCoroutine
21-
import kotlinx.coroutines.experimental.Job
20+
import kotlinx.coroutines.experimental.*
2221
import kotlinx.coroutines.experimental.channels.ProducerScope
2322
import kotlinx.coroutines.experimental.channels.SendChannel
24-
import kotlinx.coroutines.experimental.handleCoroutineException
25-
import kotlinx.coroutines.experimental.newCoroutineContext
2623
import kotlinx.coroutines.experimental.selects.SelectClause2
2724
import kotlinx.coroutines.experimental.selects.SelectInstance
2825
import kotlinx.coroutines.experimental.sync.Mutex
2926
import org.reactivestreams.Publisher
3027
import org.reactivestreams.Subscriber
3128
import org.reactivestreams.Subscription
29+
import kotlin.coroutines.experimental.ContinuationInterceptor
3230
import kotlin.coroutines.experimental.CoroutineContext
3331
import kotlin.coroutines.experimental.startCoroutine
3432

3533
/**
3634
* Creates cold reactive [Publisher] that runs a given [block] in a coroutine.
37-
* Every time the returned publisher is subscribed, it starts a new coroutine in the specified [context].
35+
* Every time the returned publisher is subscribed, it starts a new coroutine.
3836
* Coroutine emits items with `send`. Unsubscribing cancels running coroutine.
3937
*
4038
* Invocations of `send` are suspended appropriately when subscribers apply back-pressure and to ensure that
@@ -45,9 +43,19 @@ import kotlin.coroutines.experimental.startCoroutine
4543
* | `send` | `onNext`
4644
* | Normal completion or `close` without cause | `onComplete`
4745
* | Failure with exception or `close` with cause | `onError`
46+
*
47+
* The [context] for the new coroutine can be explicitly specified.
48+
* See [CoroutineDispatcher] for the standard context implementations that are provided by `kotlinx.coroutines`.
49+
* The [context][CoroutineScope.context] of the parent coroutine from its [scope][CoroutineScope] may be used,
50+
* in which case the [Job] of the resulting coroutine is a child of the job of the parent coroutine.
51+
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [DefaultDispatcher] is used.
52+
*
53+
* @param context context of the coroutine. The default value is [DefaultDispatcher].
54+
* @param block the coroutine code.
4855
*/
56+
@JvmOverloads // for binary compatibility with older code compiled before context had a default
4957
public fun <T> publish(
50-
context: CoroutineContext,
58+
context: CoroutineContext = DefaultDispatcher,
5159
block: suspend ProducerScope<T>.() -> Unit
5260
): Publisher<T> = Publisher { subscriber ->
5361
val newContext = newCoroutineContext(context)

0 commit comments

Comments
 (0)