@@ -131,17 +131,28 @@ internal class ByteBufferChannel(
131
131
var _allocated : ReadWriteBufferState .Initial ? = null
132
132
val (old, newState) = updateState { state ->
133
133
when {
134
- joining != null -> return null
135
- closed != null -> throw closed!! .sendException
134
+ joining != null -> {
135
+ _allocated ?.let { releaseBuffer(it) }
136
+ return null
137
+ }
138
+ closed != null -> {
139
+ _allocated ?.let { releaseBuffer(it) }
140
+ throw closed!! .sendException
141
+ }
136
142
state == = ReadWriteBufferState .IdleEmpty -> {
137
143
val allocated = _allocated ? : newBuffer().also { _allocated = it }
138
144
allocated.startWriting()
139
145
}
140
- state == = ReadWriteBufferState .Terminated -> throw closed!! .sendException
146
+ state == = ReadWriteBufferState .Terminated -> {
147
+ _allocated ?.let { releaseBuffer(it) }
148
+ if (joining != null ) return null
149
+ throw closed!! .sendException
150
+ }
141
151
else -> state.startWriting()
142
152
}
143
153
}
144
154
155
+ // joining?.let { restoreStateAfterWrite(); return null }
145
156
if (closed != null ) {
146
157
restoreStateAfterWrite()
147
158
tryTerminate()
@@ -247,34 +258,44 @@ internal class ByteBufferChannel(
247
258
}
248
259
249
260
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
-
261
+ if (! tryReleaseBuffer()) return false
259
262
ensureClosedJoined(joined)
260
263
261
- ReadOp .getAndSet( this , null )?.resumeWithException (IllegalStateException (" Joining is in progress" ))
262
- WriteOp .getAndSet( this , null )?. resume( Unit )
264
+ resumeReadOp (IllegalStateException (" Joining is in progress" ))
265
+ resumeWriteOp() // here we don't resume it with exception because it should resume and delegate writing
263
266
264
267
return true
265
268
}
266
269
267
270
private fun tryTerminate (): Boolean {
268
- val closed = closed ? : return false
271
+ if (closed == null ) return false
272
+
273
+ if (! tryReleaseBuffer()) return false
274
+
275
+ joining?.let { ensureClosedJoined(it) }
276
+
277
+ resumeReadOp()
278
+ resumeWriteOp()
279
+
280
+ return true
281
+ }
269
282
283
+ private fun tryReleaseBuffer (): Boolean {
270
284
var toRelease: ReadWriteBufferState .Initial ? = null
271
285
272
286
updateState { state ->
287
+ toRelease?.let { buffer ->
288
+ toRelease = null
289
+ buffer.capacity.resetForWrite()
290
+ resumeWriteOp()
291
+ }
292
+ val closed = closed
293
+
273
294
when {
274
295
state == = ReadWriteBufferState .Terminated -> return true
275
296
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
297
+ closed != null && state is ReadWriteBufferState .IdleNonEmpty && (state.capacity.tryLockForRelease() || closed.cause != null ) -> {
298
+ if (closed.cause != null ) state.capacity.forceLockForRelease()
278
299
toRelease = state.initial
279
300
ReadWriteBufferState .Terminated
280
301
}
@@ -288,13 +309,6 @@ internal class ByteBufferChannel(
288
309
}
289
310
}
290
311
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
312
return true
299
313
}
300
314
@@ -1795,7 +1809,17 @@ internal class ByteBufferChannel(
1795
1809
suspend override fun <A : Appendable > readUTF8LineTo (out : A , limit : Int ) = readUTF8LineToAscii(out , limit)
1796
1810
1797
1811
private fun resumeReadOp () {
1798
- ReadOp .getAndSet(this , null )?.resume(true )
1812
+ ReadOp .getAndSet(this , null )?.apply {
1813
+ val closedCause = closed?.cause
1814
+ when {
1815
+ closedCause != null -> resumeWithException(closedCause)
1816
+ else -> resume(true )
1817
+ }
1818
+ }
1819
+ }
1820
+
1821
+ private fun resumeReadOp (result : Throwable ) {
1822
+ ReadOp .getAndSet(this , null )?.resumeWithException(result)
1799
1823
}
1800
1824
1801
1825
private fun resumeWriteOp () {
@@ -1805,6 +1829,10 @@ internal class ByteBufferChannel(
1805
1829
}
1806
1830
}
1807
1831
1832
+ private fun resumeWriteOp (cause : Throwable ) {
1833
+ WriteOp .getAndSet(this , null )?.resumeWithException(cause)
1834
+ }
1835
+
1808
1836
private fun resumeClosed (cause : Throwable ? ) {
1809
1837
ReadOp .getAndSet(this , null )?.let { c ->
1810
1838
if (cause != null )
0 commit comments