@@ -61,7 +61,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
61
61
*/
62
62
protected open fun offerSelectInternal (element : E , select : SelectInstance <* >): Any {
63
63
// offer atomically with select
64
- val offerOp = describeTryOffer(element, select )
64
+ val offerOp = describeTryOffer(element)
65
65
val failure = select.performAtomicTrySelect(offerOp)
66
66
if (failure != null ) return failure
67
67
val receive = offerOp.result
@@ -322,29 +322,31 @@ 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 , select : SelectInstance < * > ): TryOfferDesc <E > =
326
- TryOfferDesc (element, select, queue)
325
+ protected fun describeTryOffer (element : E ): TryOfferDesc <E > =
326
+ TryOfferDesc (element, queue)
327
327
328
328
/* *
329
329
* @suppress **This is unstable API and it is subject to change.**
330
330
*/
331
331
protected class TryOfferDesc <E >(
332
332
@JvmField val element : E ,
333
- override val select : SelectInstance <* >,
334
333
queue : LockFreeLinkedListHead
335
- ) : RemoveFirstDesc<ReceiveOrClosed<E>>(queue), SelectInstanceDesc {
334
+ ) : RemoveFirstDesc<ReceiveOrClosed<E>>(queue), AtomicSelectDesc {
336
335
@JvmField var resumeToken: Any? = null
337
336
337
+ override var selectOp: Any? = null
338
+
338
339
override fun failure (affected : LockFreeLinkedListNode , next : Any ): Any? {
339
340
if (affected !is ReceiveOrClosed <* >) return OFFER_FAILED
340
341
if (affected is Closed <* >) return affected
341
342
return null
342
343
}
343
344
344
- override fun validatePrepared (node : ReceiveOrClosed <E >): Boolean {
345
- val token = node.tryResumeReceive(element, idempotent = this ) ? : return false
345
+ override fun validatePrepared (node : ReceiveOrClosed <E >): Any? {
346
+ val token = node.tryResumeReceive(element, idempotent = this ) ? : return REMOVE_PREPARED
347
+ if (token == = SELECT_RETRY ) return OFFER_FAILED
346
348
resumeToken = token
347
- return true
349
+ return null
348
350
}
349
351
}
350
352
@@ -446,8 +448,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
446
448
@JvmField val select : SelectInstance <R >,
447
449
@JvmField val block : suspend (SendChannel <E >) -> R
448
450
) : LockFreeLinkedListNode(), Send, DisposableHandle {
449
- override fun tryResumeSend (idempotent : Any? ): Any? =
450
- if (select.trySelect(idempotent)) SELECT_STARTED else null
451
+ override fun tryResumeSend (idempotent : Any? ): Any? = select.trySelectIdempotent(idempotent)
451
452
452
453
override fun completeResumeSend (token : Any ) {
453
454
assert { token == = SELECT_STARTED }
@@ -463,7 +464,7 @@ internal abstract class AbstractSendChannel<E> : SendChannel<E> {
463
464
}
464
465
465
466
override fun resumeSendClosed (closed : Closed <* >) {
466
- if (select.trySelect(null ))
467
+ if (select.trySelect())
467
468
select.resumeSelectCancellableWithException(closed.sendException)
468
469
}
469
470
@@ -523,7 +524,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
523
524
*/
524
525
protected open fun pollSelectInternal (select : SelectInstance <* >): Any? {
525
526
// poll atomically with select
526
- val pollOp = describeTryPoll(select )
527
+ val pollOp = describeTryPoll()
527
528
val failure = select.performAtomicTrySelect(pollOp)
528
529
if (failure != null ) return failure
529
530
val send = pollOp.result
@@ -652,31 +653,33 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
652
653
/* *
653
654
* @suppress **This is unstable API and it is subject to change.**
654
655
*/
655
- protected fun describeTryPoll (select : SelectInstance < * > ): TryPollDesc <E > =
656
- TryPollDesc (select, queue)
656
+ protected fun describeTryPoll (): TryPollDesc <E > =
657
+ TryPollDesc (queue)
657
658
658
659
/* *
659
660
* @suppress **This is unstable API and it is subject to change.**
660
661
*/
661
662
protected class TryPollDesc <E >(
662
- override val select : SelectInstance <* >,
663
663
queue : LockFreeLinkedListHead
664
- ) : RemoveFirstDesc<Send>(queue), SelectInstanceDesc {
665
- @JvmField var resumeToken: Any? = null
664
+ ) : RemoveFirstDesc<Send>(queue), AtomicSelectDesc {
665
+ @JvmField var resumeToken: Any? = null // can be SELECT_RETRY
666
666
@JvmField var pollResult: E ? = null
667
667
668
+ override var selectOp: Any? = null
669
+
668
670
override fun failure (affected : LockFreeLinkedListNode , next : Any ): Any? {
669
671
if (affected is Closed <* >) return affected
670
672
if (affected !is Send ) return POLL_FAILED
671
673
return null
672
674
}
673
675
674
676
@Suppress(" UNCHECKED_CAST" )
675
- override fun validatePrepared (node : Send ): Boolean {
676
- val token = node.tryResumeSend(idempotent = this ) ? : return false
677
+ override fun validatePrepared (node : Send ): Any? {
678
+ val token = node.tryResumeSend(idempotent = this ) ? : return REMOVE_PREPARED
679
+ if (token == = SELECT_RETRY ) return POLL_FAILED
677
680
resumeToken = token
678
681
pollResult = node.pollResult as E
679
- return true
682
+ return null
680
683
}
681
684
}
682
685
@@ -752,7 +755,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
752
755
pollResult == = POLL_FAILED -> {} // retry
753
756
pollResult is Closed <* > -> {
754
757
if (pollResult.closeCause == null ) {
755
- if (select.trySelect(null ))
758
+ if (select.trySelect())
756
759
block.startCoroutineUnintercepted(null , select.completion)
757
760
return
758
761
} else {
@@ -971,8 +974,10 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
971
974
@JvmField val block : suspend (Any? ) -> R ,
972
975
@JvmField val receiveMode : Int
973
976
) : Receive<E>(), DisposableHandle {
974
- override fun tryResumeReceive (value : E , idempotent : Any? ): Any? =
975
- if (select.trySelect(idempotent)) (value ? : NULL_VALUE ) else null
977
+ override fun tryResumeReceive (value : E , idempotent : Any? ): Any? {
978
+ val result = select.trySelectIdempotent(idempotent)
979
+ return if (result == = SELECT_STARTED ) value ? : NULL_VALUE else result
980
+ }
976
981
977
982
@Suppress(" UNCHECKED_CAST" )
978
983
override fun completeResumeReceive (token : Any ) {
@@ -981,7 +986,7 @@ internal abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E
981
986
}
982
987
983
988
override fun resumeReceiveClosed (closed : Closed <* >) {
984
- if (! select.trySelect(null )) return
989
+ if (! select.trySelect()) return
985
990
when (receiveMode) {
986
991
RECEIVE_THROWS_ON_CLOSE -> select.resumeSelectCancellableWithException(closed.receiveException)
987
992
RECEIVE_RESULT -> block.startCoroutine(ValueOrClosed .closed<R >(closed.closeCause), select.completion)
@@ -1032,10 +1037,6 @@ internal val POLL_FAILED: Any = Symbol("POLL_FAILED")
1032
1037
@SharedImmutable
1033
1038
internal val ENQUEUE_FAILED : Any = Symbol (" ENQUEUE_FAILED" )
1034
1039
1035
- @JvmField
1036
- @SharedImmutable
1037
- internal val SELECT_STARTED : Any = Symbol (" SELECT_STARTED" )
1038
-
1039
1040
@JvmField
1040
1041
@SharedImmutable
1041
1042
internal val NULL_VALUE : Symbol = Symbol (" NULL_VALUE" )
@@ -1059,6 +1060,7 @@ internal typealias Handler = (Throwable?) -> Unit
1059
1060
*/
1060
1061
internal interface Send {
1061
1062
val pollResult: Any? // E | Closed
1063
+ // Returns: null - failure, SELECT_RETRY for retry (only when idempotent != null), otherwise token for completeResumeSend
1062
1064
fun tryResumeSend (idempotent : Any? ): Any?
1063
1065
fun completeResumeSend (token : Any )
1064
1066
fun resumeSendClosed (closed : Closed <* >)
@@ -1069,6 +1071,7 @@ internal interface Send {
1069
1071
*/
1070
1072
internal interface ReceiveOrClosed <in E > {
1071
1073
val offerResult: Any // OFFER_SUCCESS | Closed
1074
+ // Returns: null - failure, SELECT_RETRY for retry (only when idempotent != null), otherwise token for completeResumeReceive
1072
1075
fun tryResumeReceive (value : E , idempotent : Any? ): Any?
1073
1076
fun completeResumeReceive (token : Any )
1074
1077
}
0 commit comments