blob: 653c9bd54bc4b8ae4c8846539a272f61581922c2 [file] [log] [blame]
Roman Elizarov3754f952017-01-18 20:47:54 +03001package kotlinx.coroutines.experimental
2
3import java.util.concurrent.TimeUnit
4import kotlin.coroutines.ContinuationInterceptor
5
6/**
Roman Elizarovd528e3e2017-01-23 15:40:05 +03007 * This dispatcher _feature_ is implemented by [CoroutineDispatcher] implementations that natively support
8 * non-blocking [delay] function.
Roman Elizarov3754f952017-01-18 20:47:54 +03009 */
10public interface Delay {
11 /**
12 * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
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 * immediately resumes with [CancellationException].
16 */
17 suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
18 require(time >= 0) { "Delay time $time cannot be negative" }
19 if (time <= 0) return // don't delay
Roman Elizarovd528e3e2017-01-23 15:40:05 +030020 return suspendCancellableCoroutine { scheduleResumeAfterDelay(time, unit, it) }
Roman Elizarov3754f952017-01-18 20:47:54 +030021 }
22
23 /**
Roman Elizarovd528e3e2017-01-23 15:40:05 +030024 * Schedules resume of a specified [continuation] after a specified delay [time].
Roman Elizarov3754f952017-01-18 20:47:54 +030025 */
Roman Elizarovd528e3e2017-01-23 15:40:05 +030026 fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>)
Roman Elizarov3754f952017-01-18 20:47:54 +030027}
28
29/**
30 * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
31 * This suspending function is cancellable.
32 * If the [Job] of the current coroutine is completed while this suspending function is suspended, this function
33 * immediately resumes with [CancellationException].
34 *
35 * This function delegates to [Delay] implementation of the context [CoroutineDispatcher] if possible,
36 * otherwise it resumes using a built-in single-threaded scheduled executor service.
37 */
38suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
39 require(time >= 0) { "Delay time $time cannot be negative" }
40 if (time <= 0) return // don't delay
41 return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
42 (cont.context[ContinuationInterceptor] as? Delay)?.apply {
Roman Elizarovd528e3e2017-01-23 15:40:05 +030043 scheduleResumeAfterDelay(time, unit, cont)
Roman Elizarov3754f952017-01-18 20:47:54 +030044 return@sc
45 }
Roman Elizarov67891d82017-01-23 16:47:20 +030046 scheduledExecutor.scheduleResumeAfterDelay(time, unit, cont)
Roman Elizarov3754f952017-01-18 20:47:54 +030047 }
48}