All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.selects.OnTimeout.kt Maven / Gradle / Ivy

package kotlinx.coroutines.selects

import kotlinx.coroutines.*
import kotlin.time.*

/**
 * Clause that selects the given [block] after a specified timeout passes.
 * If timeout is negative or zero, [block] is selected immediately.
 *
 * **Note: This is an experimental api.** It may be replaced with light-weight timer/timeout channels in the future.
 *
 * @param timeMillis timeout time in milliseconds.
 */
@ExperimentalCoroutinesApi
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public fun  SelectBuilder.onTimeout(timeMillis: Long, block: suspend () -> R): Unit =
    OnTimeout(timeMillis).selectClause.invoke(block)

/**
 * Clause that selects the given [block] after the specified [timeout] passes.
 * If timeout is negative or zero, [block] is selected immediately.
 *
 * **Note: This is an experimental api.** It may be replaced with light-weight timer/timeout channels in the future.
 */
@ExperimentalCoroutinesApi
public fun  SelectBuilder.onTimeout(timeout: Duration, block: suspend () -> R): Unit =
    onTimeout(timeout.toDelayMillis(), block)

/**
 * We implement [SelectBuilder.onTimeout] as a clause, so each invocation creates
 * an instance of [OnTimeout] that specifies the registration part according to
 * the [timeout][timeMillis] parameter.
 */
private class OnTimeout(
    private val timeMillis: Long
) {
    @Suppress("UNCHECKED_CAST")
    val selectClause: SelectClause0
        get() = SelectClause0Impl(
            clauseObject = this@OnTimeout,
            regFunc = OnTimeout::register as RegistrationFunction
        )

    @Suppress("UNUSED_PARAMETER")
    private fun register(select: SelectInstance<*>, ignoredParam: Any?) {
        // Should this clause complete immediately?
        if (timeMillis <= 0) {
            select.selectInRegistrationPhase(Unit)
            return
        }
        // Invoke `trySelect` after the timeout is reached.
        val action = Runnable {
            select.trySelect(this@OnTimeout, Unit)
        }
        select as SelectImplementation<*>
        val context = select.context
        val disposableHandle = context.delay.invokeOnTimeout(timeMillis, action, context)
        // Do not forget to clean-up when this `select` is completed or cancelled.
        select.disposeOnCompletion(disposableHandle)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy