Exerosis
01/11/2022, 10:24 PMephemient
01/11/2022, 10:48 PMExerosis
01/11/2022, 11:35 PMephemient
01/11/2022, 11:56 PMsuspendCoroutine
is type-safe, unlike suspendCoroutineUninterceptedOrReturn
.Exerosis
01/12/2022, 12:06 AMsuspend fun switchThreads() = suspendCoroutineUninterceptedOrReturn<Unit> {
Thread({
it.resumeWith(Result.success(Unit))
}, "Example Thread").start()
COROUTINE_SUSPENDED
}
fun main() = runBlocking {
println(Thread.currentThread())
switchThreads()
println(Thread.currentThread())
}
To print:
Thread[main,...]
Thread[Test,...]
ephemient
01/12/2022, 12:26 AMephemient
01/12/2022, 12:27 AMval fib = DeepRecursiveFunction { if (it < 2) it else callRecursive(it - 1) + callRecursive(it - 2) }
uses kotlin.coroutines (not concurrency nor kotlinx.coroutines) and does not StackOverflowExerosis
01/12/2022, 12:35 AMephemient
01/12/2022, 12:40 AMExerosis
01/12/2022, 12:51 AMval provider = SocketProvider(executor)
val dispatcher = executor.asCoroutineDispatcher()
GlobalScope.launch(dispatcher) {
while (provider.isOpen) {
val client = provider.accept() //suspends
launch(dispatcher) {
while (client.isOpen) {
val length = <http://client.read.int|client.read.int>() //suspends
val bytes = client.read.bytes(length)
println(bytes.toString(UTF_8))
}
}
}
}
I want it to for example resume from int() on some executor thread... and call bytes on the same thread... rather than scheduling a new task when I resume from int() b/c I'm already on a thread pool thread.
And I want to minimize overhead to the greatest possible degree since ofc the number of calls to something like int or bytes might be incredibly high. I've gone to great lengths to make sure that it has an almost constant memory overhead already.Nick Allen
01/12/2022, 5:47 PMresumes are always* dispatched to avoid blowing up the stack
DeepRecursiveFunction
avoids stack overflows because its implementation trampolines. There's nothing inherent to continuations that avoids stack overflow.Nick Allen
01/12/2022, 6:11 PMI want it to for example resume from int() on some executor thread... and call bytes on the same thread... rather than scheduling a new task when I resume from int() b/c I'm already on a thread pool thread.All the built in Dispatchers either schedule the task or trampoline (even Unconfined may not resume directly) If you want to guarantee you don't schedule, then
Executor { it.run() }.asCoroutineDispatcher()
is an option but it's a very dangerous option. Personally, I'd prefer it over suspendCoroutineUninterceptedOrReturn
since it's the caller aiming at their own foot rather than the implementation ignoring the caller's interceptor.Nick Allen
01/12/2022, 6:14 PMNick Allen
01/12/2022, 6:27 PMval provider = SocketProvider(executor)
val dispatcher = executor.asCoroutineDispatcher()
GlobalScope.launch(dispatcher) {
while (provider.isOpen) {
val client = provider.accept() //suspends
withContext(Dispatchers.Unconfined) {
while (client.isOpen) {
//Assuming int always resumes from executor
val length = <http://client.read.int|client.read.int>() //suspends
val bytes = client.read.bytes(length)
println(bytes.toString(UTF_8))
}
}
}
}
Exerosis
01/13/2022, 6:28 AM