Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 1 | package kotlinx.coroutines.experimental |
| 2 | |
| 3 | import kotlin.coroutines.ContinuationInterceptor |
| 4 | |
| 5 | /** |
| 6 | * This dispatcher _feature_ is implemented by [CoroutineDispatcher] implementations that |
Roman Elizarov | 67891d8 | 2017-01-23 16:47:20 +0300 | [diff] [blame^] | 7 | * natively support [yield] function. It shall be implemented only by [CoroutineDispatcher] |
| 8 | * classes with non-trivial [CoroutineDispatcher.isDispatchNeeded] implementations. |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 9 | */ |
| 10 | public interface Yield { |
| 11 | /** |
| 12 | * Yields a thread (or thread pool) of this dispatcher to other coroutines to run. |
| 13 | * This suspending function is cancellable. |
| 14 | * If the [Job] of the current coroutine is completed while this suspending function is suspended, this function |
| 15 | * resumes with [CancellationException]. |
| 16 | */ |
| 17 | suspend fun yield(): Unit = suspendCancellableCoroutine { cont -> scheduleResume(cont) } |
| 18 | |
| 19 | /** |
| 20 | * Schedules resume of a specified [continuation] in this dispatcher's thread (or pool of threads). |
| 21 | */ |
| 22 | fun scheduleResume(continuation: CancellableContinuation<Unit>) |
| 23 | } |
| 24 | |
| 25 | /** |
| 26 | * Yields a thread (or thread pool) of the current coroutine dispatcher to other coroutines to run. |
| 27 | * If the coroutine dispatcher does not have its own thread pool (like [Here] dispatcher) and does not implement |
| 28 | * [Yield], then the [Yield] implementation is taken from the context, if there is none, then this |
| 29 | * function does nothing, but checks if the coroutine [Job] was cancelled. |
| 30 | * This suspending function is cancellable. |
| 31 | * If the [Job] of the current coroutine is completed while this suspending function is suspended, this function |
| 32 | * resumes with [CancellationException]. |
| 33 | */ |
| 34 | suspend fun yield(): Unit = suspendCancellableCoroutine sc@ { cont -> |
| 35 | (cont.context[ContinuationInterceptor] as? Yield)?.apply { |
| 36 | scheduleResume(cont) |
| 37 | return@sc |
| 38 | } |
| 39 | cont.resume(Unit) |
| 40 | } |