blob: be83abfcbd6d2a29b8cc48cda41e0e9329f08c31 [file] [log] [blame]
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.experimental.io.internal
import kotlinx.coroutines.experimental.*
import kotlin.coroutines.experimental.coroutineContext
import kotlin.coroutines.experimental.intrinsics.*
/**
* This is completely similar to [kotlinx.coroutines.experimental.channels.RendezvousChannel] except:
* - non-cancellable
* - all functions are inline and always tail-call suspend
* - no poll/offer
*/
internal class InlineRendezvousSwap<T : Any> {
private val senderCont = MutableDelegateContinuation<Unit>()
private val receiverCont = MutableDelegateContinuation<T>()
@Suppress("NOTHING_TO_INLINE")
suspend inline fun send(e: T) = suspendCoroutineOrReturn<Unit> { c ->
val result = try {
senderCont.swap(c)
} catch (t: Throwable) {
receiverCont.resumeWithException(t)
throw t
}
receiverCont.resume(e)
result
}
@Suppress("NOTHING_TO_INLINE")
suspend inline fun receive(): T = suspendCoroutineOrReturn { c ->
val result = try {
receiverCont.swap(c)
} catch (t: Throwable) {
senderCont.resumeWithException(t)
throw t
}
senderCont.resume(Unit)
result
}
}
fun main(args: Array<String>) {
val ch = InlineRendezvousSwap<String>()
runBlocking {
launch(coroutineContext) {
repeat(2) {
val e = ch.receive()
println(e)
}
}
launch(coroutineContext) {
ch.send("1")
ch.send("2")
}
}
}