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.
-
listenattaches a newReceivePortto an existingSendPort.By contrast,Chanonly provides the ability to duplicate an existingReceivePort.Edit: I was mistaken:
listenis essentially equivalent todupChan, whereasduplicateis new. -
sendManysends 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,writeList2Chandoes work on infinite streams, whereassendManydoes not. -
foldis a generalization ofgetChanContents, potentially avoiding some data structures. -
splitcuts an existing channel into two channels. It gives you back a newReceivePortassociated with the existingSendPort, and a newSendPortassociated with the existingReceivePorts. This is a more general operator than one I’ve used in a few places to transparently swap out backend services.Chandoes not provide thesplitoperator, 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 aSendPortin anMVartends 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.