Skip to content

Instantly share code, notes, and snippets.

@omkar-tenkale
Created June 3, 2023 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save omkar-tenkale/06f11e23a1ba6e667db5a733b07772b4 to your computer and use it in GitHub Desktop.
Save omkar-tenkale/06f11e23a1ba6e667db5a733b07772b4 to your computer and use it in GitHub Desktop.
import android.os.Handler
import android.os.Looper
import kotlin.concurrent.thread
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
sealed class Dispatcher : CoroutineContext.Element {
object Main : Dispatcher()
object Background : Dispatcher()
override val key = DispatcherKey
}
object DispatcherKey : CoroutineContext.Key<Dispatcher> {}
class DispatcherContinuation<T>(
override val context: CoroutineContext,
val continuation: Continuation<T>
) : Continuation<T> {
override fun resumeWith(result: Result<T>) {
when (context as Dispatcher) {
Dispatcher.Main -> Handler(Looper.getMainLooper()).post {
continuation.resumeWith(result)
}
Dispatcher.Background -> thread {
continuation.resumeWith(result)
}
}
}
}
fun launch(dispatcher: Dispatcher, block: suspend () -> Unit) {
val callback = object : Continuation<Unit> {
override val context = dispatcher
override fun resumeWith(result: Result<Unit>) {}
}
block.createCoroutine(callback).resumeWith(Result.success(Unit))
}
suspend fun <R> withContext(dispatcher: Dispatcher, block: suspend () -> R): R {
return suspendCoroutine<R> { cont ->
val callback = object : Continuation<R> {
override val context = dispatcher
override fun resumeWith(result: Result<R>) {
cont.resumeWith(result)
}
}
val coroutine = block.createCoroutineUnintercepted(callback)
DispatcherContinuation(dispatcher, coroutine).resumeWith(Result.success(Unit))
}
}
fun <T> (suspend () -> T).createCoroutine(
completion: Continuation<T>
): Continuation<Unit> {
val coroutine = createCoroutineUnintercepted(completion)
return DispatcherContinuation(completion.context,coroutine)
}
suspend fun <T> suspendCoroutine(block: (Continuation<T>) -> Unit): T {
return suspendCoroutineUninterceptedOrReturn { cont ->
val dispatchedContinuation = DispatcherContinuation(cont.context, cont)
block(dispatchedContinuation)
COROUTINE_SUSPENDED
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment