@@ -45,6 +45,17 @@ sealed trait Channel[F[_], A] {
45
45
*/
46
46
def send (a : A ): F [Either [Channel .Closed , Unit ]]
47
47
48
+ /** Attempts to send an element through this channel, and indicates if
49
+ * it succeeded (`true`) or not (`false`).
50
+ *
51
+ * It can be called concurrently by multiple producers, and it may
52
+ * not succeed if the channel is bounded or synchronous. It will
53
+ * never semantically block.
54
+ *
55
+ * No-op if the channel is closed, see [[close ]] for further info.
56
+ */
57
+ def trySend (a : A ): F [Either [Channel .Closed , Boolean ]]
58
+
48
59
/** The stream of elements sent through this channel.
49
60
* It terminates if [[close ]] is called and all elements in the channel
50
61
* have been emitted (see [[close ]] for futher info).
@@ -145,33 +156,48 @@ object Channel {
145
156
F .uncancelable { poll =>
146
157
state.modify {
147
158
case s @ State (_, _, _, _, closed @ true ) =>
148
- (s, Channel .closed.pure[F ])
159
+ (s, Channel .closed[ Unit ] .pure[F ])
149
160
150
161
case State (values, size, waiting, producers, closed @ false ) =>
151
162
if (size < capacity)
152
163
(
153
164
State (a :: values, size + 1 , None , producers, false ),
154
- notifyStream(waiting)
165
+ notifyStream(waiting).as(rightUnit)
155
166
)
156
167
else
157
168
(
158
169
State (values, size, None , (a, producer) :: producers, false ),
159
- notifyStream(waiting) <* waitOnBound(producer, poll)
170
+ notifyStream(waiting).as(rightUnit) <* waitOnBound(producer, poll)
160
171
)
161
172
}.flatten
162
173
}
163
174
}
164
175
176
+ def trySend (a : A ) =
177
+ state.modify {
178
+ case s @ State (_, _, _, _, closed @ true ) =>
179
+ (s, Channel .closed[Boolean ].pure[F ])
180
+
181
+ case s @ State (values, size, waiting, producers, closed @ false ) =>
182
+ if (size < capacity)
183
+ (
184
+ State (a :: values, size + 1 , None , producers, false ),
185
+ notifyStream(waiting).as(rightTrue)
186
+ )
187
+ else
188
+ (s, rightFalse.pure[F ])
189
+ }.flatten
190
+
165
191
def close =
166
192
state
167
193
.modify {
168
194
case s @ State (_, _, _, _, closed @ true ) =>
169
- (s, Channel .closed.pure[F ])
195
+ (s, Channel .closed[ Unit ] .pure[F ])
170
196
171
197
case State (values, size, waiting, producers, closed @ false ) =>
172
198
(
173
199
State (values, size, None , producers, true ),
174
- notifyStream(waiting) <* signalClosure
200
+ notifyStream(waiting).as(rightUnit) <* signalClosure
175
201
)
176
202
}
177
203
.flatten
@@ -219,7 +245,7 @@ object Channel {
219
245
}.flatten
220
246
221
247
def notifyStream (waitForChanges : Option [Deferred [F , Unit ]]) =
222
- waitForChanges.traverse(_.complete(())).as(rightUnit)
248
+ waitForChanges.traverse(_.complete(()))
223
249
224
250
def waitOnBound (producer : Deferred [F , Unit ], poll : Poll [F ]) =
225
251
poll(producer.get).onCancel {
@@ -248,6 +274,9 @@ object Channel {
248
274
}
249
275
250
276
// allocate once
251
- private final val closed : Either [Closed , Unit ] = Left (Closed )
277
+ @ inline private final def closed [A ]: Either [Closed , A ] = _closed
278
+ private [this ] final val _closed : Either [Closed , Nothing ] = Left (Closed )
252
279
private final val rightUnit : Either [Closed , Unit ] = Right (())
280
+ private final val rightTrue : Either [Closed , Boolean ] = Right (true )
281
+ private final val rightFalse : Either [Closed , Boolean ] = Right (false )
253
282
}
0 commit comments