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