Hopac allows to synchronously give
value to a channel which will block if no-one is listening, and to asynchronously send
which will buffer the values if they are not read.
I would like to do something in-between: to give a value if there is a listener, or to proceed without blocking or buffering the value if there is none. Is there a way to do it?
You can implement polling give
and take
operations using the alternative mechanism of Hopac. Here is a possible signature for such polling operations:
module Ch =
module Poll =
val give: Ch<'x> -> 'x -> Job<bool>
val take: Ch<'x> -> Job<option<'x>>
And here is an implementation of that signature:
module Ch =
module Poll =
let give xCh x =
Alt.pick (xCh <-? x >>%? true <|> Alt.always false)
let take xCh =
Alt.pick (xCh |>>? Some <|> Alt.always None)
The way these work is that the left hand side alternative is committed to if it is available. Otherwise the right hand side alternative is committed to because it is always available.
Note that that these only make sense if it is indeed the case that the other side of the communication is waiting on the channel. If both ends try to poll, communication is unlikely to happen.
The Concurrent ML library that Hopac is based upon directly provides polling operations. It would also be possible to implement polling operations as optimized primitives within Hopac.
Update: I've added polling, or non-blocking, give
and take
operations as optimized primitives on synchronous channels to Hopac. They are provided by the Ch.Try module.