asynchronousf#hopac

Hopac -- can I give value to a channel only if someone is listening to it?


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?


Solution

  • 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.