File tree Expand file tree Collapse file tree 2 files changed +36
-1
lines changed
kotlinx-coroutines-core/src
main/kotlin/kotlinx/coroutines/experimental/channels
test/kotlin/kotlinx/coroutines/experimental/channels Expand file tree Collapse file tree 2 files changed +36
-1
lines changed Original file line number Diff line number Diff line change @@ -47,6 +47,11 @@ public interface SendChannel<in E> {
4747 * or throws [ClosedSendChannelException] if the channel [isClosedForSend] _normally_.
4848 * It throws the original [close] cause exception if the channel has _failed_.
4949 *
50+ * Note, that closing a channel _after_ this function had suspended does not cause this suspended send invocation
51+ * to abort, because closing a channel is conceptually like sending a special "close token" over this channel.
52+ * All elements that are sent over the channel are delivered in first-in first-out order. The element that
53+ * is being sent will get delivered to receivers before a close token.
54+ *
5055 * This suspending function is cancellable. If the [Job] of the current coroutine is completed while this
5156 * function is suspended, this function immediately resumes with [CancellationException].
5257 * Cancellation of suspended send is *atomic* -- when this function
@@ -77,7 +82,7 @@ public interface SendChannel<in E> {
7782 /* *
7883 * Closes this channel with an optional exceptional [cause].
7984 * This is an idempotent operation -- repeated invocations of this function have no effect and return `false`.
80- * Conceptually, its sends a special close token of this channel. Immediately after invocation of this function
85+ * Conceptually, its sends a special " close token" over this channel. Immediately after invocation of this function
8186 * [isClosedForSend] starts returning `true`. However, [isClosedForReceive][ReceiveChannel.isClosedForReceive]
8287 * on the side of [ReceiveChannel] starts returning `true` only after all previously sent elements
8388 * are received.
Original file line number Diff line number Diff line change @@ -20,6 +20,8 @@ import kotlinx.coroutines.experimental.TestBase
2020import kotlinx.coroutines.experimental.launch
2121import kotlinx.coroutines.experimental.runBlocking
2222import kotlinx.coroutines.experimental.yield
23+ import org.hamcrest.core.IsEqual
24+ import org.hamcrest.core.IsNull
2325import org.junit.Assert.*
2426import org.junit.Test
2527
@@ -247,6 +249,34 @@ class RendezvousChannelTest : TestBase() {
247249 finish(10 )
248250 }
249251
252+ @Test
253+ fun testSuspendSendOnClosedChannel () = runBlocking<Unit > {
254+ val q = RendezvousChannel <Int >()
255+ expect(1 )
256+ launch(context) {
257+ expect(4 )
258+ q.send(42 ) // suspend
259+ expect(11 )
260+ }
261+ expect(2 )
262+ launch(context) {
263+ expect(5 )
264+ q.close()
265+ expect(6 )
266+ }
267+ expect(3 )
268+ yield () // to sender
269+ expect(7 )
270+ yield () // try to resume sender (it will not resume despite the close!)
271+ expect(8 )
272+ assertThat(q.receiveOrNull(), IsEqual (42 ))
273+ expect(9 )
274+ assertThat(q.receiveOrNull(), IsNull ())
275+ expect(10 )
276+ yield () // to sender, it was resumed!
277+ finish(12 )
278+ }
279+
250280 class BadClass {
251281 override fun equals (other : Any? ): Boolean = error(" equals" )
252282 override fun hashCode (): Int = error(" hashCode" )
You can’t perform that action at this time.
0 commit comments