1- /*
2- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3- */
4-
51@file:JvmMultifileClass
62@file:JvmName(" ChannelsKt" )
73
84package kotlinx.coroutines.channels
95
106import kotlinx.coroutines.*
7+ import kotlin.jvm.*
118
129/* *
13- * **Deprecated** blocking variant of send.
14- * This method is deprecated in the favour of [trySendBlocking].
15- *
16- * `sendBlocking` is a dangerous primitive — it throws an exception
17- * if the channel was closed or, more commonly, cancelled.
18- * Cancellation exceptions in non-blocking code are unexpected and frequently
19- * trigger internal failures.
20- *
21- * These bugs are hard-to-spot during code review and they forced users to write
22- * their own wrappers around `sendBlocking`.
23- * So this function is deprecated and replaced with a more explicit primitive.
24- *
25- * The real-world example of broken usage with Firebase:
26- *
27- * ```kotlin
28- * callbackFlow {
29- * val listener = object : ValueEventListener {
30- * override fun onDataChange(snapshot: DataSnapshot) {
31- * // This line may fail and crash the app when the downstream flow is cancelled
32- * sendBlocking(DataSnapshot(snapshot))
33- * }
34- *
35- * override fun onCancelled(error: DatabaseError) {
36- * close(error.toException())
37- * }
38- * }
39- *
40- * firebaseQuery.addValueEventListener(listener)
41- * awaitClose { firebaseQuery.removeEventListener(listener) }
42- * }
43- * ```
44- */
45- @Deprecated(
46- level = DeprecationLevel .ERROR ,
47- message = " Deprecated in the favour of 'trySendBlocking'. " +
48- " Consider handling the result of 'trySendBlocking' explicitly and rethrow exception if necessary" ,
49- replaceWith = ReplaceWith (" trySendBlocking(element)" )
50- ) // WARNING in 1.5.0, ERROR in 1.6.0, HIDDEN in 1.7.0
51- public fun <E > SendChannel<E>.sendBlocking (element : E ) {
52- // fast path
53- if (trySend(element).isSuccess)
54- return
55- // slow path
56- runBlocking {
57- send(element)
58- }
59- }
60-
61- /* *
62- * Adds [element] into to this channel, **blocking** the caller while this channel is full,
10+ * Adds [element] to this channel, **blocking** the caller while this channel is full,
6311 * and returning either [successful][ChannelResult.isSuccess] result when the element was added, or
6412 * failed result representing closed channel with a corresponding exception.
6513 *
@@ -77,9 +25,8 @@ public fun <E> SendChannel<E>.sendBlocking(element: E) {
7725 *
7826 * For this operation it is guaranteed that [failure][ChannelResult.failed] always contains an exception in it.
7927 *
80- * @throws [ InterruptedException] if the current thread is interrupted during the blocking send operation.
28+ * @throws ` InterruptedException` on JVM if the current thread is interrupted during the blocking send operation.
8129 */
82- @Throws(InterruptedException ::class )
8330public fun <E > SendChannel<E>.trySendBlocking (element : E ): ChannelResult <Unit > {
8431 /*
8532 * Sent successfully -- bail out.
@@ -94,3 +41,20 @@ public fun <E> SendChannel<E>.trySendBlocking(element: E): ChannelResult<Unit> {
9441 else ChannelResult .closed(r.exceptionOrNull())
9542 }
9643}
44+
45+ /* * @suppress */
46+ @Deprecated(
47+ level = DeprecationLevel .ERROR ,
48+ message = " Deprecated in the favour of 'trySendBlocking'. " +
49+ " Consider handling the result of 'trySendBlocking' explicitly and rethrow exception if necessary" ,
50+ replaceWith = ReplaceWith (" trySendBlocking(element)" )
51+ ) // WARNING in 1.5.0, ERROR in 1.6.0, HIDDEN in 1.7.0
52+ public fun <E > SendChannel<E>.sendBlocking (element : E ) {
53+ // fast path
54+ if (trySend(element).isSuccess)
55+ return
56+ // slow path
57+ runBlocking {
58+ send(element)
59+ }
60+ }
0 commit comments