blob: a78ad07d4f197584f99c7935348b923a1cd0b230 [file] [log] [blame]
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03001package kotlinx.coroutines.experimental.io.internal
2
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03003import kotlinx.coroutines.experimental.*
Ilya Gorbunov81f79c32018-04-17 19:59:50 +03004import kotlin.coroutines.experimental.coroutineContext
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03005import kotlin.coroutines.experimental.intrinsics.*
6
7/**
8 * This is completely similar to [kotlinx.coroutines.experimental.channels.RendezvousChannel] except:
9 * - non-cancellable
10 * - all functions are inline and always tail-call suspend
11 * - no poll/offer
12 */
13internal class InlineRendezvousSwap<T : Any> {
Sergey Mashkov0939f232017-12-22 19:57:30 +030014 private val senderCont = MutableDelegateContinuation<Unit>()
15 private val receiverCont = MutableDelegateContinuation<T>()
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +030016
17 @Suppress("NOTHING_TO_INLINE")
18 suspend inline fun send(e: T) = suspendCoroutineOrReturn<Unit> { c ->
19 val result = try {
20 senderCont.swap(c)
21 } catch (t: Throwable) {
22 receiverCont.resumeWithException(t)
23 throw t
24 }
25
26 receiverCont.resume(e)
27 result
28 }
29
30 @Suppress("NOTHING_TO_INLINE")
31 suspend inline fun receive(): T = suspendCoroutineOrReturn { c ->
32 val result = try {
33 receiverCont.swap(c)
34 } catch (t: Throwable) {
35 senderCont.resumeWithException(t)
36 throw t
37 }
38
39 senderCont.resume(Unit)
40 result
41 }
42
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +030043}
44
45fun main(args: Array<String>) {
46 val ch = InlineRendezvousSwap<String>()
47 runBlocking {
48 launch(coroutineContext) {
49 repeat(2) {
50 val e = ch.receive()
51 println(e)
52 }
53 }
54 launch(coroutineContext) {
55 ch.send("1")
56 ch.send("2")
57 }
58 }
59}