1
1
package com.gitlab.dhorman.cryptotrader.util
2
2
3
- import io.vavr.Tuple2
4
- import io.vavr.collection.HashMap
5
- import io.vavr.collection.Map
6
3
import kotlinx.coroutines.*
7
4
import kotlinx.coroutines.channels.Channel
8
5
import kotlinx.coroutines.channels.ProducerScope
@@ -28,7 +25,6 @@ private open class ShareOperator<T>(
28
25
private val gracePeriod : Duration ? = null ,
29
26
private val scope : CoroutineScope ? = null
30
27
) {
31
- private var subscribers = 0L
32
28
private val subscriberChannels = mutableSetOf<SendChannel <T >>()
33
29
private val subscriberChannelsMutex = Mutex ()
34
30
private val upstreamSubscriptionLock = Mutex ()
@@ -57,8 +53,8 @@ private open class ShareOperator<T>(
57
53
}
58
54
}
59
55
} catch (e: CancellationException ) {
60
- if (subscriberChannels.size > 0 ) {
61
- logger.warn(" upstream cancelled when subscriberChannels (${subscriberChannels.size} ) variable is not empty." )
56
+ if (subscriberChannels.isNotEmpty() ) {
57
+ logger.warn(" $ upstream cancelled when subscriberChannels (${subscriberChannels.size} ) variable is not empty." )
62
58
}
63
59
throw e
64
60
}
@@ -123,7 +119,7 @@ private open class ShareOperator<T>(
123
119
val shareOperator = channelFlow<T > {
124
120
try {
125
121
upstreamSubscriptionLock.withLock {
126
- if (++ subscribers == 1L ) {
122
+ if (subscriberChannels.isEmpty() ) {
127
123
cancelGracePeriodTimerJob()
128
124
processQueueAndSubscribeSelf()
129
125
subscribeToUpstream()
@@ -138,7 +134,7 @@ private open class ShareOperator<T>(
138
134
upstreamSubscriptionLock.withLock {
139
135
unsubscribeSelf()
140
136
141
- if (-- subscribers == 0L ) {
137
+ if (subscriberChannels.isEmpty() ) {
142
138
val launched = launchGracePeriodTimerJob()
143
139
144
140
if (! launched) {
@@ -197,18 +193,21 @@ fun <T> Channel<T>.buffer(scope: CoroutineScope, timespan: Duration): Channel<Li
197
193
return upstream
198
194
}
199
195
200
- fun <K , V > flowFromMap (map : Map <K , V >): Flow <Tuple2 <K , V >> = flow {
201
- map.forEach { emit(it) }
202
- }
203
-
204
- suspend fun <K , V > Flow <Tuple2 <K , V >>.collectMap (): Map <K , V > {
205
- var map = HashMap .empty<K , V >()
196
+ private object AbortException : Throwable(" " , null , true , false )
206
197
207
- collect {
208
- map = map.put(it)
198
+ suspend fun <T > Flow<T>.first (): T {
199
+ var result: T ? = null
200
+ try {
201
+ collect { value ->
202
+ result = value
203
+ throw AbortException
204
+ }
205
+ } catch (e: AbortException ) {
206
+ // Do nothing
209
207
}
210
208
211
- return map
209
+ if (result == null ) throw NoSuchElementException (" Expected at least one element" )
210
+ return result!!
212
211
}
213
212
214
213
suspend fun <T > Flow<T>.firstOrNull (): T ? {
@@ -217,9 +216,9 @@ suspend fun <T> Flow<T>.firstOrNull(): T? {
217
216
try {
218
217
collect {
219
218
result = it
220
- throw CancellationException ()
219
+ throw AbortException
221
220
}
222
- } catch (e: CancellationException ) {
221
+ } catch (e: AbortException ) {
223
222
// Ignore
224
223
}
225
224
0 commit comments