1
- /*
2
- * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3
- */
4
-
5
1
@file:JvmMultifileClass
6
2
@file:JvmName(" ChannelsKt" )
7
3
8
4
package kotlinx.coroutines.channels
9
5
10
6
import kotlinx.coroutines.*
7
+ import kotlin.jvm.*
11
8
12
9
/* *
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,
63
11
* and returning either [successful][ChannelResult.isSuccess] result when the element was added, or
64
12
* failed result representing closed channel with a corresponding exception.
65
13
*
@@ -77,9 +25,8 @@ public fun <E> SendChannel<E>.sendBlocking(element: E) {
77
25
*
78
26
* For this operation it is guaranteed that [failure][ChannelResult.failed] always contains an exception in it.
79
27
*
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.
81
29
*/
82
- @Throws(InterruptedException ::class )
83
30
public fun <E > SendChannel<E>.trySendBlocking (element : E ): ChannelResult <Unit > {
84
31
/*
85
32
* Sent successfully -- bail out.
@@ -94,3 +41,20 @@ public fun <E> SendChannel<E>.trySendBlocking(element: E): ChannelResult<Unit> {
94
41
else ChannelResult .closed(r.exceptionOrNull())
95
42
}
96
43
}
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