• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package benchmarks.tailcall
6 
7 import kotlinx.coroutines.*
8 import kotlin.coroutines.*
9 import kotlin.coroutines.intrinsics.*
10 
11 @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
12 public abstract class SimpleChannel {
13     companion object {
14         const val NULL_SURROGATE: Int = -1
15     }
16 
17     @JvmField
18     protected var producer: Continuation<Unit>? = null
19     @JvmField
20     protected var enqueuedValue: Int = NULL_SURROGATE
21     @JvmField
22     protected var consumer: Continuation<Int>? = null
23 
sendnull24     suspend fun send(element: Int) {
25         require(element != NULL_SURROGATE)
26         if (offer(element)) {
27             return
28         }
29 
30         return suspendSend(element)
31     }
32 
offernull33     private fun offer(element: Int): Boolean {
34         if (consumer == null) {
35             return false
36         }
37 
38         consumer!!.resume(element)
39         consumer = null
40         return true
41     }
42 
receivenull43     suspend fun receive(): Int {
44         // Cached value
45         if (enqueuedValue != NULL_SURROGATE) {
46             val result = enqueuedValue
47             enqueuedValue = NULL_SURROGATE
48             producer!!.resume(Unit)
49             return result
50         }
51 
52         return suspendReceive()
53     }
54 
suspendReceivenull55     abstract suspend fun suspendReceive(): Int
56     abstract suspend fun suspendSend(element: Int)
57 }
58 
59 class NonCancellableChannel : SimpleChannel() {
60     override suspend fun suspendReceive(): Int = suspendCoroutineUninterceptedOrReturn {
61         consumer = it.intercepted()
62         COROUTINE_SUSPENDED
63     }
64 
65     override suspend fun suspendSend(element: Int) = suspendCoroutineUninterceptedOrReturn<Unit> {
66         enqueuedValue = element
67         producer = it.intercepted()
68         COROUTINE_SUSPENDED
69     }
70 }
71 
72 class CancellableChannel : SimpleChannel() {
<lambda>null73     override suspend fun suspendReceive(): Int = suspendCancellableCoroutine {
74         consumer = it.intercepted()
75         COROUTINE_SUSPENDED
76     }
77 
<lambda>null78     override suspend fun suspendSend(element: Int) = suspendCancellableCoroutine<Unit> {
79         enqueuedValue = element
80         producer = it.intercepted()
81         COROUTINE_SUSPENDED
82     }
83 }
84 
85 class CancellableReusableChannel : SimpleChannel() {
86     @Suppress("INVISIBLE_MEMBER")
<lambda>null87     override suspend fun suspendReceive(): Int = suspendCancellableCoroutineReusable {
88         consumer = it.intercepted()
89         COROUTINE_SUSPENDED
90     }
91 
92     @Suppress("INVISIBLE_MEMBER")
<lambda>null93     override suspend fun suspendSend(element: Int) = suspendCancellableCoroutineReusable<Unit> {
94         enqueuedValue = element
95         producer = it.intercepted()
96         COROUTINE_SUSPENDED
97     }
98 }
99