5
5
package kotlinx.coroutines.channels
6
6
7
7
import kotlinx.coroutines.*
8
+ import kotlinx.coroutines.RESUME_TOKEN
8
9
import kotlinx.coroutines.internal.*
9
10
import kotlinx.coroutines.selects.*
10
11
import kotlin.math.*
@@ -45,6 +46,7 @@ internal open class ArrayChannel<E>(
45
46
// result is `OFFER_SUCCESS | OFFER_FAILED | Closed`
46
47
protected override fun offerInternal (element : E ): Any {
47
48
var receive: ReceiveOrClosed <E >? = null
49
+ var token: Any? = null
48
50
state.withLock {
49
51
val size = state.size
50
52
closedForSend?.let { return it }
@@ -59,9 +61,8 @@ internal open class ArrayChannel<E>(
59
61
state.size = size // restore size
60
62
return receive!!
61
63
}
62
- val token = receive!! .tryResumeReceive(element, null )
64
+ token = receive!! .tryResumeReceive(element, null )
63
65
if (token != null ) {
64
- assert { token == = RESUME_TOKEN }
65
66
state.size = size // restore size
66
67
return @withLock
67
68
}
@@ -75,13 +76,14 @@ internal open class ArrayChannel<E>(
75
76
return OFFER_FAILED
76
77
}
77
78
// breaks here if offer meets receiver
78
- receive!! .completeResumeReceive(element)
79
+ receive!! .completeResumeReceive(element, token !! )
79
80
return receive!! .offerResult
80
81
}
81
82
82
83
// result is `ALREADY_SELECTED | OFFER_SUCCESS | OFFER_FAILED | Closed`
83
84
protected override fun offerSelectInternal (element : E , select : SelectInstance <* >): Any {
84
85
var receive: ReceiveOrClosed <E >? = null
86
+ var token: Any? = null
85
87
state.withLock {
86
88
val size = state.size
87
89
closedForSend?.let { return it }
@@ -97,6 +99,7 @@ internal open class ArrayChannel<E>(
97
99
failure == null -> { // offered successfully
98
100
state.size = size // restore size
99
101
receive = offerOp.result
102
+ token = offerOp.takeToken()
100
103
return @withLock
101
104
}
102
105
failure == = OFFER_FAILED -> break @loop // cannot offer -> Ok to queue to buffer
@@ -122,7 +125,7 @@ internal open class ArrayChannel<E>(
122
125
return OFFER_FAILED
123
126
}
124
127
// breaks here if offer meets receiver
125
- receive!! .completeResumeReceive(element)
128
+ receive!! .completeResumeReceive(element, token !! )
126
129
return receive!! .offerResult
127
130
}
128
131
@@ -133,6 +136,7 @@ internal open class ArrayChannel<E>(
133
136
// result is `E | POLL_FAILED | Closed`
134
137
protected override fun pollInternal (): Any? {
135
138
var send: Send ? = null
139
+ var token: Any? = null
136
140
var resumed = false
137
141
var result: Any? = null
138
142
state.withLock {
@@ -148,9 +152,8 @@ internal open class ArrayChannel<E>(
148
152
loop@ while (true ) {
149
153
send = takeFirstSendOrPeekClosed() ? : break
150
154
disposeQueue { send as ? Closed <* > }
151
- val token = send!! .tryResumeSend(null )
155
+ token = send!! .tryResumeSend(null )
152
156
if (token != null ) {
153
- assert { token == = RESUME_TOKEN }
154
157
resumed = true
155
158
replacement = send!! .pollResult
156
159
break @loop
@@ -165,7 +168,7 @@ internal open class ArrayChannel<E>(
165
168
}
166
169
// complete send the we're taken replacement from
167
170
if (resumed)
168
- send!! .completeResumeSend()
171
+ send!! .completeResumeSend(token !! )
169
172
return result
170
173
}
171
174
@@ -174,6 +177,7 @@ internal open class ArrayChannel<E>(
174
177
var send: Send ? = null
175
178
var success = false
176
179
var result: Any? = null
180
+ var token: Any? = null
177
181
state.withLock {
178
182
val size = state.size
179
183
if (size == 0 ) return closedForSend ? : POLL_FAILED
@@ -190,6 +194,7 @@ internal open class ArrayChannel<E>(
190
194
when {
191
195
failure == null -> { // polled successfully
192
196
send = pollOp.result
197
+ token = pollOp.takeToken()
193
198
success = true
194
199
replacement = send!! .pollResult
195
200
break @loop
@@ -203,6 +208,7 @@ internal open class ArrayChannel<E>(
203
208
}
204
209
failure is Closed <* > -> {
205
210
send = failure
211
+ token = RESUME_TOKEN // :KLUDGE: We know that's the token to resume failed send`
206
212
success = true
207
213
replacement = failure
208
214
break @loop
@@ -226,7 +232,7 @@ internal open class ArrayChannel<E>(
226
232
}
227
233
// complete send the we're taken replacement from
228
234
if (success)
229
- send!! .completeResumeSend()
235
+ send!! .completeResumeSend(token !! )
230
236
return result
231
237
}
232
238
0 commit comments