The split-channel package is new library that is a small variation on Control.Concurrent.Chan. The most obvious change is that it splits the channel into sending and receiving ports. This has at least two advantages: first, that this enables the type system to more finely constrain program behavior, and second, a SendPort
can have zero ReceivePorts
associated with it, and messages written to such a channel can be garbage collected.
This library started life last fall as part of my experiments in adding support for PostgreSQL’s asynchronous notifications to Chris Done’s native pgsql-simple library. The initial motivation was that if a notification arrived and nobody was listening, I wanted to be able to garbage collect it. However, the type advantages are what keep me coming back.
Beyond the primary change, this library has a number of other small improvements over Control.Concurrent.Chan
: the deprecated thread-unsafe functions aren’t there, and several operators have been added or improved, most notably listen
, sendMany
, fold
, and split
.
-
listen
attaches a newReceivePort
to an existingSendPort
.By contrast,Chan
only provides the ability to duplicate an existingReceivePort
.Edit: I was mistaken:
listen
is essentially equivalent todupChan
, whereasduplicate
is new. -
sendMany
sends a list of messages atomically. It’s a better name thanwriteList2Chan
, which is not atomic and is only a convenience function written in terms ofsend
. However,writeList2Chan
does work on infinite streams, whereassendMany
does not. -
fold
is a generalization ofgetChanContents
, potentially avoiding some data structures. -
split
cuts an existing channel into two channels. It gives you back a newReceivePort
associated with the existingSendPort
, and a newSendPort
associated with the existingReceivePorts
. This is a more general operator than one I’ve used in a few places to transparently swap out backend services.Chan
does not provide thesplit
operator, though one could be added. However I am skeptical that this is a good idea: it’s just a little too effect-ful for comfort. I think that putting aSendPort
in anMVar
tends to be a better idea than usingsplit
, even though it does introduce another layer of indirection.
Finally, a few acknowledgements are in order: primarily, Control.Concurrent.Chan
and its authors and contributors, and secondarily, Joey Adams for GHC Bug #5870, the fix of which has been incorporated into split-channel.