@@ -142,6 +142,7 @@ internal class ByteBufferChannel(
142
142
}
143
143
}
144
144
145
+ joining?.let { restoreStateAfterWrite(); tryCompleteJoining(it); return null }
145
146
if (closed != null ) {
146
147
restoreStateAfterWrite()
147
148
tryTerminate()
@@ -247,34 +248,44 @@ internal class ByteBufferChannel(
247
248
}
248
249
249
250
private fun tryCompleteJoining (joined : JoiningState ): Boolean {
250
- updateState { state ->
251
- when {
252
- state == = ReadWriteBufferState .Terminated -> state
253
- state == = ReadWriteBufferState .IdleEmpty -> ReadWriteBufferState .Terminated
254
- // we don't handle IdleNonEmpty as it should be switched to IdleEmpty in restoreStateAfterRead
255
- else -> return false
256
- }
257
- }
258
-
251
+ if (! tryReleaseBuffer()) return false
259
252
ensureClosedJoined(joined)
260
253
261
- ReadOp .getAndSet( this , null )?.resumeWithException (IllegalStateException (" Joining is in progress" ))
262
- WriteOp .getAndSet( this , null )?. resume( Unit )
254
+ resumeReadOp (IllegalStateException (" Joining is in progress" ))
255
+ resumeWriteOp() // here we don't resume it with exception because it should resume and delegate writing
263
256
264
257
return true
265
258
}
266
259
267
260
private fun tryTerminate (): Boolean {
268
- val closed = closed ? : return false
261
+ if ( closed == null ) return false
269
262
263
+ if (! tryReleaseBuffer()) return false
264
+
265
+ joining?.let { ensureClosedJoined(it) }
266
+
267
+ resumeReadOp()
268
+ resumeWriteOp()
269
+
270
+ return true
271
+ }
272
+
273
+ private fun tryReleaseBuffer (): Boolean {
270
274
var toRelease: ReadWriteBufferState .Initial ? = null
271
275
272
276
updateState { state ->
277
+ toRelease?.let { buffer ->
278
+ toRelease = null
279
+ buffer.capacity.resetForWrite()
280
+ resumeWriteOp()
281
+ }
282
+ val closed = closed
283
+
273
284
when {
274
285
state == = ReadWriteBufferState .Terminated -> return true
275
286
state == = ReadWriteBufferState .IdleEmpty -> ReadWriteBufferState .Terminated
276
- closed.cause != null && state is ReadWriteBufferState .IdleNonEmpty -> {
277
- // here we don't need to tryLockForRelease as we already have closed state
287
+ closed != null && state is ReadWriteBufferState .IdleNonEmpty && (state.capacity.tryLockForRelease() || closed.cause != null ) -> {
288
+ if (closed.cause != null ) state.capacity.forceLockForRelease()
278
289
toRelease = state.initial
279
290
ReadWriteBufferState .Terminated
280
291
}
@@ -288,13 +299,6 @@ internal class ByteBufferChannel(
288
299
}
289
300
}
290
301
291
- joining?.let { ensureClosedJoined(it) }
292
-
293
- WriteOp .getAndSet(this , null )?.resumeWithException(closed.sendException)
294
- ReadOp .getAndSet(this , null )?.apply {
295
- if (closed.cause != null ) resumeWithException(closed.cause) else resume(false )
296
- }
297
-
298
302
return true
299
303
}
300
304
@@ -1795,7 +1799,17 @@ internal class ByteBufferChannel(
1795
1799
suspend override fun <A : Appendable > readUTF8LineTo (out : A , limit : Int ) = readUTF8LineToAscii(out , limit)
1796
1800
1797
1801
private fun resumeReadOp () {
1798
- ReadOp .getAndSet(this , null )?.resume(true )
1802
+ ReadOp .getAndSet(this , null )?.apply {
1803
+ val closedCause = closed?.cause
1804
+ when {
1805
+ closedCause != null -> resumeWithException(closedCause)
1806
+ else -> resume(true )
1807
+ }
1808
+ }
1809
+ }
1810
+
1811
+ private fun resumeReadOp (result : Throwable ) {
1812
+ ReadOp .getAndSet(this , null )?.resumeWithException(result)
1799
1813
}
1800
1814
1801
1815
private fun resumeWriteOp () {
@@ -1805,6 +1819,10 @@ internal class ByteBufferChannel(
1805
1819
}
1806
1820
}
1807
1821
1822
+ private fun resumeWriteOp (cause : Throwable ) {
1823
+ WriteOp .getAndSet(this , null )?.resumeWithException(cause)
1824
+ }
1825
+
1808
1826
private fun resumeClosed (cause : Throwable ? ) {
1809
1827
ReadOp .getAndSet(this , null )?.let { c ->
1810
1828
if (cause != null )
0 commit comments