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

commonMain.org.luaj.vm2.internal.RunBlockingNonSuspensions.kt Maven / Gradle / Ivy

Go to download

LUAK - Kotlin port of LuaJ (fork of https://github.com/korlibs/korge-luak)

There is a newer version: 1.0.0-alpha3
Show newest version
package org.luaj.vm2.internal

import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn

fun  runBlockingNoSuspensionsNullable(callback: suspend () -> T): T {
    return runBlockingNoSuspensions {
        Result.success(callback())
    }.getOrThrow()
}

/**
 * Allows to execute a suspendable block as long as you can ensure no suspending will happen at all..
 */
fun  T.noSuspend(callback: suspend T.() -> R): R {
    return runBlockingNoSuspensions { callback(this@noSuspend) }
}

/**
 * Allows to execute a suspendable block as long as you can ensure no suspending will happen at all..
 */
//@OptIn(InternalCoroutinesApi::class)
fun  runBlockingNoSuspensions(callback: suspend () -> T): T {
    //println("!!!!! runBlockingNoSuspensions")
    //TODO("runBlockingNoSuspensions not supported yet!")
    var completed = false
    lateinit var rresult: T
    var resultEx: Throwable? = null
    var suspendCount = 0

    callback.startCoroutineUndispatched(object : Continuation {
        override val context: CoroutineContext = object : AbstractCoroutineContextElement(ContinuationInterceptor),
            ContinuationInterceptor {//, Delay {
            override val key: CoroutineContext.Key<*> = ContinuationInterceptor.Key
            override fun  interceptContinuation(continuation: Continuation): Continuation = continuation.also { suspendCount++ }
            //override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation) = continuation.resume(Unit)
        }

        private val unitInstance get() = Unit

        override fun resumeWith(result: Result) {
            val exception = result.exceptionOrNull()
            if (exception != null) {
                resultEx = exception
                completed = true
                //println("COMPLETED WITH EXCEPTION: exception=$exception")
                exception.printStackTrace()
            } else {
                val rvalue = result.getOrThrow() ?: (unitInstance as T) // @TODO: Kotlin-js BUG returns undefined instead of Unit! In runBlockingNoSuspensions { uncompress(i.toAsyncInputStream(), o.toAsyncOutputStream()) }
                //if (rvalue == null) error("ERROR: unexpected completed value=$value, rvalue=$rvalue, suspendCount=$suspendCount")
                rresult = rvalue
                completed = true
                //println("COMPLETED WITH RESULT: result=$result, value=$rvalue")
            }
        }
    })
    if (!completed) throw Exception("runBlockingNoSuspensions was not completed synchronously! suspendCount=$suspendCount")
    if (resultEx != null) throw resultEx!!
    return rresult
}

private fun  (suspend () -> T).startCoroutineUndispatched(completion: Continuation) {
    startDirect(completion) {
        withCoroutineContext(completion.context, null) {
            startCoroutineUninterceptedOrReturn(completion)
        }
    }
}

private inline fun  startDirect(completion: Continuation, block: () -> Any?) {
    val value = try {
        block()
    } catch (e: Throwable) {
        completion.resumeWithException(e)
        return
    }
    if (value !== COROUTINE_SUSPENDED) {
        @Suppress("UNCHECKED_CAST")
        completion.resume(value as T)
    }
}

private inline fun  withCoroutineContext(context: CoroutineContext, countOrElement: Any?, block: () -> T): T = block()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy