blob: be83abfcbd6d2a29b8cc48cda41e0e9329f08c31 [file] [log] [blame]
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03001/*
2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03005package kotlinx.coroutines.experimental.io.internal
6
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03007import kotlinx.coroutines.experimental.*
Ilya Gorbunov81f79c32018-04-17 19:59:50 +03008import kotlin.coroutines.experimental.coroutineContext
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +03009import kotlin.coroutines.experimental.intrinsics.*
10
11/**
12 * This is completely similar to [kotlinx.coroutines.experimental.channels.RendezvousChannel] except:
13 * - non-cancellable
14 * - all functions are inline and always tail-call suspend
15 * - no poll/offer
16 */
17internal class InlineRendezvousSwap<T : Any> {
Sergey Mashkov0939f232017-12-22 19:57:30 +030018 private val senderCont = MutableDelegateContinuation<Unit>()
19 private val receiverCont = MutableDelegateContinuation<T>()
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +030020
21 @Suppress("NOTHING_TO_INLINE")
22 suspend inline fun send(e: T) = suspendCoroutineOrReturn<Unit> { c ->
23 val result = try {
24 senderCont.swap(c)
25 } catch (t: Throwable) {
26 receiverCont.resumeWithException(t)
27 throw t
28 }
29
30 receiverCont.resume(e)
31 result
32 }
33
34 @Suppress("NOTHING_TO_INLINE")
35 suspend inline fun receive(): T = suspendCoroutineOrReturn { c ->
36 val result = try {
37 receiverCont.swap(c)
38 } catch (t: Throwable) {
39 senderCont.resumeWithException(t)
40 throw t
41 }
42
43 senderCont.resume(Unit)
44 result
45 }
46
Sergey Mashkov4ee9cfb2017-12-20 18:22:11 +030047}
48
49fun main(args: Array<String>) {
50 val ch = InlineRendezvousSwap<String>()
51 runBlocking {
52 launch(coroutineContext) {
53 repeat(2) {
54 val e = ch.receive()
55 println(e)
56 }
57 }
58 launch(coroutineContext) {
59 ch.send("1")
60 ch.send("2")
61 }
62 }
63}