@@ -56,7 +56,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
56
56
57
57
/* *
58
58
* Tries to add element to buffer or to queued receiver if select statement clause was not selected yet.
59
- * Return type is `ALREADY_SELECTED | OFFER_SUCCESS | OFFER_FAILED | Closed`.
59
+ * Return type is `ALREADY_SELECTED | OFFER_SUCCESS | OFFER_FAILED | RETRY_ATOMIC | Closed`.
60
60
* @suppress **This is unstable API and it is subject to change.**
61
61
*/
62
62
protected open fun offerSelectInternal (element : E , select : SelectInstance <* >): Any {
@@ -322,7 +322,8 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
322
322
/* *
323
323
* @suppress **This is unstable API and it is subject to change.**
324
324
*/
325
- protected fun describeTryOffer (element : E ): TryOfferDesc <E > = TryOfferDesc (element, queue)
325
+ protected fun describeTryOffer (element : E ): TryOfferDesc <E > =
326
+ TryOfferDesc (element, queue)
326
327
327
328
/* *
328
329
* @suppress **This is unstable API and it is subject to change.**
@@ -339,10 +340,11 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
339
340
else -> null
340
341
}
341
342
342
- override fun validatePrepared (node : ReceiveOrClosed <E >): Boolean {
343
- val token = node.tryResumeReceive(element, idempotent = this ) ? : return false
343
+ override fun validatePrepared (node : ReceiveOrClosed <E >): Any? {
344
+ val token = node.tryResumeReceive(element, idempotent = this ) ? : return REMOVE_PREPARED
345
+ if (token == = RETRY_ATOMIC ) return RETRY_ATOMIC
344
346
resumeToken = token
345
- return true
347
+ return null
346
348
}
347
349
}
348
350
@@ -358,7 +360,9 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
358
360
if (select.isSelected) return
359
361
if (full) {
360
362
val node = SendSelect (element, this , select, block)
361
- when (val enqueueResult = enqueueSend(node)) {
363
+ val enqueueResult = enqueueSend(node)
364
+ // println("enqueueSend($element) -> $enqueueResult")
365
+ when (enqueueResult) {
362
366
null -> { // enqueued successfully
363
367
select.disposeOnSelect(node)
364
368
return
@@ -374,6 +378,9 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
374
378
when {
375
379
offerResult == = ALREADY_SELECTED -> return
376
380
offerResult == = OFFER_FAILED -> {} // retry
381
+ offerResult == = RETRY_ATOMIC -> {
382
+ // println("registerSelectSend($element): RETRY")
383
+ } // retry
377
384
offerResult == = OFFER_SUCCESS -> {
378
385
block.startCoroutineUnintercepted(receiver = this , completion = select.completion)
379
386
return
@@ -423,20 +430,25 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
423
430
@JvmField val select : SelectInstance <R >,
424
431
@JvmField val block : suspend (SendChannel <E >) -> R
425
432
) : Send(), DisposableHandle {
426
- override fun tryResumeSend (idempotent : Any? ): Any? =
427
- if (select.trySelect(idempotent)) SELECT_STARTED else null
433
+ override fun tryResumeSend (idempotent : Any? ): Any? {
434
+ val result = select.trySelectIdempotent(idempotent)
435
+ // println("SendSelect($pollResult) tryResumeSend=$result")
436
+ return result
437
+ }
428
438
429
439
override fun completeResumeSend (token : Any ) {
430
440
assert { token == = SELECT_STARTED }
441
+ // println("SendSelect($pollResult) completeResumeSend")
431
442
block.startCoroutine(receiver = channel, completion = select.completion)
432
443
}
433
444
434
445
override fun dispose () { // invoked on select completion
446
+ // println("SendSelect($pollResult) dispose")
435
447
remove()
436
448
}
437
449
438
450
override fun resumeSendClosed (closed : Closed <* >) {
439
- if (select.trySelect(null ))
451
+ if (select.trySelect())
440
452
select.resumeSelectCancellableWithException(closed.sendException)
441
453
}
442
454
@@ -491,7 +503,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
491
503
492
504
/* *
493
505
* Tries to remove element from buffer or from queued sender if select statement clause was not selected yet.
494
- * Return type is `ALREADY_SELECTED | E | POLL_FAILED | Closed`
506
+ * Return type is `ALREADY_SELECTED | E | POLL_FAILED | RETRY_ATOMIC | Closed`
495
507
* @suppress **This is unstable API and it is subject to change.**
496
508
*/
497
509
protected open fun pollSelectInternal (select : SelectInstance <* >): Any? {
@@ -625,13 +637,16 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
625
637
/* *
626
638
* @suppress **This is unstable API and it is subject to change.**
627
639
*/
628
- protected fun describeTryPoll (): TryPollDesc <E > = TryPollDesc (queue)
640
+ protected fun describeTryPoll (): TryPollDesc <E > =
641
+ TryPollDesc (queue)
629
642
630
643
/* *
631
644
* @suppress **This is unstable API and it is subject to change.**
632
645
*/
633
- protected class TryPollDesc <E >(queue : LockFreeLinkedListHead ) : RemoveFirstDesc<Send>(queue) {
634
- @JvmField var resumeToken: Any? = null
646
+ protected class TryPollDesc <E >(
647
+ queue : LockFreeLinkedListHead
648
+ ) : RemoveFirstDesc<Send>(queue) {
649
+ @JvmField var resumeToken: Any? = null // can be SELECT_RETRY
635
650
@JvmField var pollResult: E ? = null
636
651
637
652
override fun failure (affected : LockFreeLinkedListNode , next : Any ): Any? = when (affected) {
@@ -641,11 +656,12 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
641
656
}
642
657
643
658
@Suppress(" UNCHECKED_CAST" )
644
- override fun validatePrepared (node : Send ): Boolean {
645
- val token = node.tryResumeSend(idempotent = this ) ? : return false
659
+ override fun validatePrepared (node : Send ): Any? {
660
+ val token = node.tryResumeSend(idempotent = this ) ? : return REMOVE_PREPARED
661
+ if (token == = RETRY_ATOMIC ) return RETRY_ATOMIC
646
662
resumeToken = token
647
663
pollResult = node.pollResult as E
648
- return true
664
+ return null
649
665
}
650
666
}
651
667
@@ -667,6 +683,9 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
667
683
when {
668
684
pollResult == = ALREADY_SELECTED -> return
669
685
pollResult == = POLL_FAILED -> {} // retry
686
+ pollResult == = RETRY_ATOMIC -> {
687
+ // println("registerSelectReceive(): RETRY")
688
+ } // retry
670
689
pollResult is Closed <* > -> throw recoverStackTrace(pollResult.receiveException)
671
690
else -> {
672
691
block.startCoroutineUnintercepted(pollResult as E , select.completion)
@@ -695,9 +714,10 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
695
714
when {
696
715
pollResult == = ALREADY_SELECTED -> return
697
716
pollResult == = POLL_FAILED -> {} // retry
717
+ pollResult == = RETRY_ATOMIC -> {} // retry
698
718
pollResult is Closed <* > -> {
699
719
if (pollResult.closeCause == null ) {
700
- if (select.trySelect(null ))
720
+ if (select.trySelect())
701
721
block.startCoroutineUnintercepted(null , select.completion)
702
722
return
703
723
} else {
@@ -732,6 +752,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
732
752
when {
733
753
pollResult == = ALREADY_SELECTED -> return
734
754
pollResult == = POLL_FAILED -> {} // retry
755
+ pollResult == = RETRY_ATOMIC -> {} // retry
735
756
pollResult is Closed <* > -> {
736
757
block.startCoroutineUnintercepted(ValueOrClosed .closed(pollResult.closeCause), select.completion)
737
758
}
@@ -913,8 +934,10 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
913
934
@JvmField val block : suspend (Any? ) -> R ,
914
935
@JvmField val receiveMode : Int
915
936
) : Receive<E>(), DisposableHandle {
916
- override fun tryResumeReceive (value : E , idempotent : Any? ): Any? =
917
- if (select.trySelect(idempotent)) (value ? : NULL_VALUE ) else null
937
+ override fun tryResumeReceive (value : E , idempotent : Any? ): Any? {
938
+ val result = select.trySelectIdempotent(idempotent)
939
+ return if (result == = SELECT_STARTED ) value ? : NULL_VALUE else result
940
+ }
918
941
919
942
@Suppress(" UNCHECKED_CAST" )
920
943
override fun completeResumeReceive (token : Any ) {
@@ -923,7 +946,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
923
946
}
924
947
925
948
override fun resumeReceiveClosed (closed : Closed <* >) {
926
- if (! select.trySelect(null )) return
949
+ if (! select.trySelect()) return
927
950
when (receiveMode) {
928
951
RECEIVE_THROWS_ON_CLOSE -> select.resumeSelectCancellableWithException(closed.receiveException)
929
952
RECEIVE_RESULT -> block.startCoroutine(ValueOrClosed .closed<R >(closed.closeCause), select.completion)
@@ -970,10 +993,6 @@ internal val POLL_FAILED: Any = Symbol("POLL_FAILED")
970
993
@SharedImmutable
971
994
internal val ENQUEUE_FAILED : Any = Symbol (" ENQUEUE_FAILED" )
972
995
973
- @JvmField
974
- @SharedImmutable
975
- internal val SELECT_STARTED : Any = Symbol (" SELECT_STARTED" )
976
-
977
996
@JvmField
978
997
@SharedImmutable
979
998
internal val NULL_VALUE : Symbol = Symbol (" NULL_VALUE" )
@@ -997,6 +1016,7 @@ internal typealias Handler = (Throwable?) -> Unit
997
1016
*/
998
1017
internal abstract class Send : LockFreeLinkedListNode () {
999
1018
abstract val pollResult: Any? // E | Closed
1019
+ // Returns: null - failure, RETRY_ATOMIC for retry (only when idempotent != null), otherwise token for completeResumeSend
1000
1020
abstract fun tryResumeSend (idempotent : Any? ): Any?
1001
1021
abstract fun completeResumeSend (token : Any )
1002
1022
abstract fun resumeSendClosed (closed : Closed <* >)
@@ -1007,6 +1027,7 @@ internal abstract class Send : LockFreeLinkedListNode() {
1007
1027
*/
1008
1028
internal interface ReceiveOrClosed <in E > {
1009
1029
val offerResult: Any // OFFER_SUCCESS | Closed
1030
+ // Returns: null - failure, RETRY_ATOMIC for retry (only when idempotent != null), otherwise token for completeResumeReceive
1010
1031
fun tryResumeReceive (value : E , idempotent : Any? ): Any?
1011
1032
fun completeResumeReceive (token : Any )
1012
1033
}
0 commit comments