@@ -8,6 +8,7 @@ import kotlinx.coroutines.*
8
8
import kotlinx.coroutines.flow.*
9
9
import org.reactivestreams.*
10
10
import java.util.concurrent.atomic.*
11
+ import kotlin.coroutines.*
11
12
12
13
/* *
13
14
* Transforms the given flow to a spec-compliant [Publisher]
@@ -18,19 +19,14 @@ public fun <T : Any> Flow<T>.asPublisher(): Publisher<T> = FlowAsPublisher(this)
18
19
19
20
/* *
20
21
* Adapter that transforms [Flow] into TCK-complaint [Publisher].
21
- * Any calls to [cancel] cancels the original flow.
22
+ * Any calls to [cancel] cancel the original flow.
22
23
*/
23
24
@Suppress(" PublisherImplementation" )
24
25
private class FlowAsPublisher <T : Any >(private val flow : Flow <T >) : Publisher<T> {
25
26
26
27
override fun subscribe (subscriber : Subscriber <in T >? ) {
27
28
if (subscriber == null ) throw NullPointerException ()
28
- subscriber.onSubscribe(
29
- FlowSubscription (
30
- flow,
31
- subscriber
32
- )
33
- )
29
+ subscriber.onSubscribe(FlowSubscription (flow, subscriber))
34
30
}
35
31
36
32
private class FlowSubscription <T >(val flow : Flow <T >, val subscriber : Subscriber <in T >) : Subscription {
@@ -45,18 +41,18 @@ private class FlowAsPublisher<T : Any>(private val flow: Flow<T>) : Publisher<T>
45
41
consumeFlow()
46
42
subscriber.onComplete()
47
43
} catch (e: Throwable ) {
48
- // Failed with real exception
44
+ // Failed with real exception, not due to cancellation
49
45
if (! coroutineContext[Job ]!! .isCancelled) {
50
46
subscriber.onError(e)
51
47
}
52
48
}
53
49
}
54
50
55
- private suspend fun CoroutineScope. consumeFlow () {
51
+ private suspend fun consumeFlow () {
56
52
flow.collect { value ->
57
- if (! isActive) {
53
+ if (! coroutineContext. isActive) {
58
54
subscriber.onComplete()
59
- yield () // Force cancellation
55
+ coroutineContext.ensureActive()
60
56
}
61
57
62
58
if (requested.get() == 0L ) {
@@ -67,7 +63,7 @@ private class FlowAsPublisher<T : Any>(private val flow: Flow<T>) : Publisher<T>
67
63
}
68
64
69
65
requested.decrementAndGet()
70
- val result = kotlin. runCatching {
66
+ val result = runCatching {
71
67
subscriber.onNext(value)
72
68
}
73
69
@@ -96,12 +92,10 @@ private class FlowAsPublisher<T : Any>(private val flow: Flow<T>) : Publisher<T>
96
92
snapshot = requested.get()
97
93
newValue = snapshot + n
98
94
if (newValue <= 0L ) newValue = Long .MAX_VALUE
99
-
100
95
} while (! requested.compareAndSet(snapshot, newValue))
101
96
102
97
val prev = producer.get()
103
98
if (prev == null || ! producer.compareAndSet(prev, null )) return
104
-
105
99
prev.resumeSafely()
106
100
}
107
101
0 commit comments