@@ -96,10 +96,10 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
96
96
* @suppress **This is unstable API and it is subject to change.**
97
97
*/
98
98
protected fun sendBuffered (element : E ): ReceiveOrClosed <* >? {
99
- queue.addLastIfPrev(SendBuffered (element), { prev ->
99
+ queue.addLastIfPrev(SendBuffered (element)) { prev ->
100
100
if (prev is ReceiveOrClosed <* >) return @sendBuffered prev
101
101
true
102
- })
102
+ }
103
103
return null
104
104
}
105
105
@@ -170,8 +170,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
170
170
private suspend fun sendSuspend (element : E ): Unit = suspendAtomicCancellableCoroutine sc@ { cont ->
171
171
val send = SendElement (element, cont)
172
172
loop@ while (true ) {
173
- val enqueueResult = enqueueSend(send)
174
- when (enqueueResult) {
173
+ when (val enqueueResult = enqueueSend(send)) {
175
174
null -> { // enqueued successfully
176
175
cont.removeOnCancellation(send)
177
176
return @sc
@@ -206,12 +205,12 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
206
205
* * ENQUEUE_FAILED -- buffer is not full (should not enqueue)
207
206
* * ReceiveOrClosed<*> -- receiver is waiting or it is closed (should not enqueue)
208
207
*/
209
- private fun enqueueSend (send : SendElement ): Any? {
208
+ private fun enqueueSend (send : Send ): Any? {
210
209
if (isBufferAlwaysFull) {
211
- queue.addLastIfPrev(send, { prev ->
210
+ queue.addLastIfPrev(send) { prev ->
212
211
if (prev is ReceiveOrClosed <* >) return @enqueueSend prev
213
212
true
214
- })
213
+ }
215
214
} else {
216
215
if (! queue.addLastIfPrevAndIf(send, { prev ->
217
216
if (prev is ReceiveOrClosed <* >) return @enqueueSend prev
@@ -346,30 +345,6 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
346
345
}
347
346
}
348
347
349
- private inner class TryEnqueueSendDesc <R >(
350
- element : E ,
351
- select : SelectInstance <R >,
352
- block : suspend (SendChannel <E >) -> R
353
- ) : AddLastDesc<SendSelect<E, R>>(queue, SendSelect (element, this@AbstractSendChannel , select, block)) {
354
- override fun failure (affected : LockFreeLinkedListNode , next : Any ): Any? {
355
- if (affected is ReceiveOrClosed <* >) {
356
- return affected as ? Closed <* > ? : ENQUEUE_FAILED
357
- }
358
- return null
359
- }
360
-
361
- override fun onPrepare (affected : LockFreeLinkedListNode , next : LockFreeLinkedListNode ): Any? {
362
- if (! isBufferFull) return ENQUEUE_FAILED
363
- return super .onPrepare(affected, next)
364
- }
365
-
366
- override fun finishOnSuccess (affected : LockFreeLinkedListNode , next : LockFreeLinkedListNode ) {
367
- super .finishOnSuccess(affected, next)
368
- // we can actually remove on select start, but this is also Ok (it'll get removed if discovered there)
369
- node.disposeOnSelect()
370
- }
371
- }
372
-
373
348
final override val onSend: SelectClause2 <E , SendChannel <E >>
374
349
get() = object : SelectClause2 <E , SendChannel <E >> {
375
350
override fun <R > registerSelectClause2 (select : SelectInstance <R >, param : E , block : suspend (SendChannel <E >) -> R ) {
@@ -381,27 +356,30 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
381
356
while (true ) {
382
357
if (select.isSelected) return
383
358
if (full) {
384
- val enqueueOp = TryEnqueueSendDesc (element, select, block)
385
- val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ? : return
386
- when {
387
- enqueueResult == = ALREADY_SELECTED -> return
388
- enqueueResult == = ENQUEUE_FAILED -> {} // retry
389
- enqueueResult is Closed <* > -> throw recoverStackTrace(enqueueResult.sendException)
390
- else -> error(" performAtomicIfNotSelected(TryEnqueueSendDesc) returned $enqueueResult " )
391
- }
392
- } else {
393
- val offerResult = offerSelectInternal(element, select)
394
- when {
395
- offerResult == = ALREADY_SELECTED -> return
396
- offerResult == = OFFER_FAILED -> {} // retry
397
- offerResult == = OFFER_SUCCESS -> {
398
- block.startCoroutineUnintercepted(receiver = this , completion = select.completion)
359
+ val node = SendSelect (element, this , select, block)
360
+ when (val enqueueResult = enqueueSend(node)) {
361
+ null -> { // enqueued successfully
362
+ select.disposeOnSelect(node)
399
363
return
400
364
}
401
- offerResult is Closed <* > -> throw recoverStackTrace(offerResult.sendException)
402
- else -> error(" offerSelectInternal returned $offerResult " )
365
+ is Closed <* > -> {
366
+ helpClose(enqueueResult)
367
+ throw recoverStackTrace(enqueueResult.sendException)
368
+ }
403
369
}
404
370
}
371
+ // hm... receiver is waiting or buffer is not full. try to offer
372
+ val offerResult = offerSelectInternal(element, select)
373
+ when {
374
+ offerResult == = ALREADY_SELECTED -> return
375
+ offerResult == = OFFER_FAILED -> {} // retry
376
+ offerResult == = OFFER_SUCCESS -> {
377
+ block.startCoroutineUnintercepted(receiver = this , completion = select.completion)
378
+ return
379
+ }
380
+ offerResult is Closed <* > -> throw recoverStackTrace(offerResult.sendException)
381
+ else -> error(" offerSelectInternal returned $offerResult " )
382
+ }
405
383
}
406
384
}
407
385
@@ -443,7 +421,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
443
421
@JvmField val channel : SendChannel <E >,
444
422
@JvmField val select : SelectInstance <R >,
445
423
@JvmField val block : suspend (SendChannel <E >) -> R
446
- ) : LockFreeLinkedListNode(), Send , DisposableHandle {
424
+ ) : Send() , DisposableHandle {
447
425
override fun tryResumeSend (idempotent : Any? ): Any? =
448
426
if (select.trySelect(idempotent)) SELECT_STARTED else null
449
427
@@ -452,11 +430,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
452
430
block.startCoroutine(receiver = channel, completion = select.completion)
453
431
}
454
432
455
- fun disposeOnSelect () {
456
- select.disposeOnSelect(this )
457
- }
458
-
459
- override fun dispose () {
433
+ override fun dispose () { // invoked on select completion
460
434
remove()
461
435
}
462
436
@@ -470,7 +444,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
470
444
471
445
internal class SendBuffered <out E >(
472
446
@JvmField val element : E
473
- ) : LockFreeLinkedListNode(), Send {
447
+ ) : Send() {
474
448
override val pollResult: Any? get() = element
475
449
override fun tryResumeSend (idempotent : Any? ): Any? = SEND_RESUMED
476
450
override fun completeResumeSend (token : Any ) { assert { token == = SEND_RESUMED } }
@@ -578,7 +552,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
578
552
579
553
private fun enqueueReceive (receive : Receive <E >): Boolean {
580
554
val result = if (isBufferAlwaysEmpty)
581
- queue.addLastIfPrev(receive, { it !is Send }) else
555
+ queue.addLastIfPrev(receive) { it !is Send } else
582
556
queue.addLastIfPrevAndIf(receive, { it !is Send }, { isBufferEmpty })
583
557
if (result) onReceiveEnqueued()
584
558
return result
@@ -674,30 +648,6 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
674
648
}
675
649
}
676
650
677
- private inner class TryEnqueueReceiveDesc <E , R >(
678
- select : SelectInstance <R >,
679
- block : suspend (Any? ) -> R ,
680
- receiveMode : Int
681
- ) : AddLastDesc<ReceiveSelect<R, E>>(queue, ReceiveSelect (select, block, receiveMode)) {
682
- override fun failure (affected : LockFreeLinkedListNode , next : Any ): Any? {
683
- if (affected is Send ) return ENQUEUE_FAILED
684
- return null
685
- }
686
-
687
- override fun onPrepare (affected : LockFreeLinkedListNode , next : LockFreeLinkedListNode ): Any? {
688
- if (! isBufferEmpty) return ENQUEUE_FAILED
689
- return super .onPrepare(affected, next)
690
- }
691
-
692
- override fun finishOnSuccess (affected : LockFreeLinkedListNode , next : LockFreeLinkedListNode ) {
693
- super .finishOnSuccess(affected, next)
694
- // notify the there is one more receiver
695
- onReceiveEnqueued()
696
- // we can actually remove on select start, but this is also Ok (it'll get removed if discovered there)
697
- node.removeOnSelectCompletion()
698
- }
699
- }
700
-
701
651
final override val onReceive: SelectClause1 <E >
702
652
get() = object : SelectClause1 <E > {
703
653
override fun <R > registerSelectClause1 (select : SelectInstance <R >, block : suspend (E ) -> R ) {
@@ -710,7 +660,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
710
660
while (true ) {
711
661
if (select.isSelected) return
712
662
if (isEmpty) {
713
- if (registerEnqueueDesc (select, block, RECEIVE_THROWS_ON_CLOSE )) return
663
+ if (enqueueReceiveSelect (select, block as suspend ( Any? ) -> R , RECEIVE_THROWS_ON_CLOSE )) return
714
664
} else {
715
665
val pollResult = pollSelectInternal(select)
716
666
when {
@@ -738,7 +688,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
738
688
while (true ) {
739
689
if (select.isSelected) return
740
690
if (isEmpty) {
741
- if (registerEnqueueDesc (select, block, RECEIVE_NULL_ON_CLOSE )) return
691
+ if (enqueueReceiveSelect (select, block as suspend ( Any? ) -> R , RECEIVE_NULL_ON_CLOSE )) return
742
692
} else {
743
693
val pollResult = pollSelectInternal(select)
744
694
when {
@@ -775,7 +725,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
775
725
while (true ) {
776
726
if (select.isSelected) return
777
727
if (isEmpty) {
778
- if (registerEnqueueDesc (select, block, RECEIVE_RESULT )) return
728
+ if (enqueueReceiveSelect (select, block as suspend ( Any? ) -> R , RECEIVE_RESULT )) return
779
729
} else {
780
730
val pollResult = pollSelectInternal(select)
781
731
when {
@@ -794,18 +744,14 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
794
744
}
795
745
}
796
746
797
- private fun <R , E > registerEnqueueDesc (
798
- select : SelectInstance <R >, block : suspend (E ) -> R ,
747
+ private fun <R > enqueueReceiveSelect (
748
+ select : SelectInstance <R >, block : suspend (Any? ) -> R ,
799
749
receiveMode : Int
800
750
): Boolean {
801
- @Suppress(" UNCHECKED_CAST" )
802
- val enqueueOp = TryEnqueueReceiveDesc <E , R >(select, block as suspend (Any? ) -> R , receiveMode)
803
- val enqueueResult = select.performAtomicIfNotSelected(enqueueOp) ? : return true
804
- return when {
805
- enqueueResult == = ALREADY_SELECTED -> true
806
- enqueueResult == = ENQUEUE_FAILED -> false // retry
807
- else -> error(" performAtomicIfNotSelected(TryEnqueueReceiveDesc) returned $enqueueResult " )
808
- }
751
+ val node = ReceiveSelect (this , select, block, receiveMode)
752
+ val result = enqueueReceive(node)
753
+ if (result) select.disposeOnSelect(node)
754
+ return result
809
755
}
810
756
811
757
// ------ protected ------
@@ -960,7 +906,8 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
960
906
override fun toString (): String = " ReceiveHasNext[$cont ]"
961
907
}
962
908
963
- private inner class ReceiveSelect <R , in E >(
909
+ private class ReceiveSelect <R , E >(
910
+ @JvmField val channel : AbstractChannel <E >,
964
911
@JvmField val select : SelectInstance <R >,
965
912
@JvmField val block : suspend (Any? ) -> R ,
966
913
@JvmField val receiveMode : Int
@@ -987,13 +934,9 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
987
934
}
988
935
}
989
936
990
- fun removeOnSelectCompletion () {
991
- select.disposeOnSelect(this )
992
- }
993
-
994
937
override fun dispose () { // invoked on select completion
995
938
if (remove())
996
- onReceiveDequeued() // notify cancellation of receive
939
+ channel. onReceiveDequeued() // notify cancellation of receive
997
940
}
998
941
999
942
override fun toString (): String = " ReceiveSelect[$select ,receiveMode=$receiveMode ]"
@@ -1051,11 +994,11 @@ internal typealias Handler = (Throwable?) -> Unit
1051
994
/* *
1052
995
* Represents sending waiter in the queue.
1053
996
*/
1054
- internal interface Send {
1055
- val pollResult: Any? // E | Closed
1056
- fun tryResumeSend (idempotent : Any? ): Any?
1057
- fun completeResumeSend (token : Any )
1058
- fun resumeSendClosed (closed : Closed <* >)
997
+ internal abstract class Send : LockFreeLinkedListNode () {
998
+ abstract val pollResult: Any? // E | Closed
999
+ abstract fun tryResumeSend (idempotent : Any? ): Any?
1000
+ abstract fun completeResumeSend (token : Any )
1001
+ abstract fun resumeSendClosed (closed : Closed <* >)
1059
1002
}
1060
1003
1061
1004
/* *
@@ -1074,7 +1017,7 @@ internal interface ReceiveOrClosed<in E> {
1074
1017
internal class SendElement (
1075
1018
override val pollResult : Any? ,
1076
1019
@JvmField val cont : CancellableContinuation <Unit >
1077
- ) : LockFreeLinkedListNode(), Send {
1020
+ ) : Send() {
1078
1021
override fun tryResumeSend (idempotent : Any? ): Any? = cont.tryResume(Unit , idempotent)
1079
1022
override fun completeResumeSend (token : Any ) = cont.completeResume(token)
1080
1023
override fun resumeSendClosed (closed : Closed <* >) = cont.resumeWithException(closed.sendException)
@@ -1086,7 +1029,7 @@ internal class SendElement(
1086
1029
*/
1087
1030
internal class Closed <in E >(
1088
1031
@JvmField val closeCause : Throwable ?
1089
- ) : LockFreeLinkedListNode(), Send , ReceiveOrClosed<E> {
1032
+ ) : Send() , ReceiveOrClosed<E> {
1090
1033
val sendException: Throwable get() = closeCause ? : ClosedSendChannelException (DEFAULT_CLOSE_MESSAGE )
1091
1034
val receiveException: Throwable get() = closeCause ? : ClosedReceiveChannelException (DEFAULT_CLOSE_MESSAGE )
1092
1035
0 commit comments