-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Control.Concurrent.Chan split into sending and receiving halves. -- -- This module splits Control.Concurrent.Chan into sending and receiving -- halves, which allows the type system to more finely constrain program -- behavior. As a secondary benefit, messages written to channels with no -- receive ports associated with them can be reliably garbage collected. -- -- In addition, this module incorporates several of clean-ups and -- additions to the venerable Chan. Most notably, the deprecated -- thread-unsafe functions have been removed, the ability to -- duplicate Receive Ports has been added, the sendMany -- operation allows for multiple messages to be sent atomically, and the -- split operation turns a single channel into two. @package split-channel @version 0.2.0.0 -- | This package provides an unbounded, imperative queue that is supposed -- to be thread safe and asynchronous exception safe. It is essentially -- the same communication mechanism as Chan, except that each -- channel is split into separate sending and receiving ends, called -- SendPort and ReceivePort respectively. This has at least -- two advantages: -- --
    --
  1. Program behavior can be more finely constrained via the type -- system.
  2. --
  3. Channels can have zero ReceivePorts associated with them. -- Messages written to such a channel disappear into the aether and can -- be garbage collected. Note that ReceivePorts can be -- subsequently attached to such a channel via listen, and can be -- detached via garbage collection.
  4. --
-- -- By contrast, Chan couples a SendPort and a -- ReceivePort together in a pair. Thus keeping a reference to a -- SendPort implies that there is at least one reference to a -- ReceivePort, which means that messages cannot be garbage -- collected from an active channel if nobody is listening. -- -- A channel can have multiple ReceivePorts. This results in a -- publish- subscribe pattern of communication: every message will be -- delivered to every port. Alternatively, multiple threads can read from -- a single port. This results in a push-pull pattern of communication, -- similar to ZeroMQ: every message will be delivered to exactly one -- thread. Of course both can be used together to form hybrid patterns of -- communication. -- -- A channel can only have one SendPort. However multiple -- threads can can safely write to a single port, allowing effects -- similar to multiple SendPorts. -- -- Some of the tradeoffs of split-channel compared to Cloud -- Haskell's Remote.Channel are: -- --
    --
  1. split-channel is restricted to in-process communications -- only.
  2. --
  3. split-channel has no restriction on the type of values -- that may be communicated.
  4. --
  5. There is a quasi-duality between the two approaches: Cloud -- Haskell's ReceivePorts are special whereas -- split-channel's SendPorts are special.
  6. --
  7. ReceivePorts can be duplicated, which -- allows for considerably more efficient publish-subscribe -- communications than supported by Cloud Haskell at the present -- time.
  8. --
module Control.Concurrent.Chan.Split -- | SendPorts represent one end of the channel. There is only one -- SendPort per channel, though it can be used from multiple -- threads. Messages can be sent to the channel using send. data SendPort a -- | ReceivePorts represent the other end of a channel. A channel -- can have many ReceivePorts, which all receive the same -- messages in a publish/subscribe like manner. A single -- ReceivePort can be used from multiple threads, where every -- message will be delivered to a single thread in a push/pull like -- manner. Use receive to fetch messages from the channel. data ReceivePort a -- | Creates a new channel and a (SendPort, ReceivePort) pair -- representing the two sides of the channel. new :: IO (SendPort a, ReceivePort a) -- | Produces a new channel that initially has zero ReceivePorts. -- Any messages written to this channel before a reader is -- listening will be eligible for garbage collection. -- Note that one can one can implement newSendPort in terms of -- new by throwing away the ReceivePort and letting it be -- garbage collected, and that one can implement new in terms of -- newSendPort and listen. newSendPort :: IO (SendPort a) -- | Send a message to a channel. This is asynchronous and does not block. send :: SendPort a -> a -> IO () -- | Fetch a message from a channel. If no message is available, it blocks -- until one is. Can be used in conjunction with System.Timeout. receive :: ReceivePort a -> IO a -- | Atomically send many messages at once. Note that this function forces -- the spine of the list beforehand to minimize the critical section, -- which also helps prevent exceptions at inopportune times. Trying to -- send an infinite list will never send anything, though it will -- allocate and retain a lot of memory trying to do so. sendMany :: SendPort a -> [a] -> IO () -- | Create a new ReceivePort attached the same channel as a given -- SendPort. This ReceivePort starts out empty, and -- remains so until more messages are written to the SendPort. listen :: SendPort a -> IO (ReceivePort a) -- | Create a new ReceivePort attached to the same channel as -- another ReceivePort. These two ports will receive the same -- messages. Any messages in the channel that have not been consumed by -- the existing port will also appear in the new port. duplicate :: ReceivePort a -> IO (ReceivePort a) -- | This function splits an existing channel in two; associating a new -- receive port with the old send port, and a new send port with the -- existing receive ports. The new receive port starts out empty, while -- the existing receive ports retain any unprocessed messages. -- split :: SendPort a -> IO (ReceivePort a, SendPort a) -- | A right fold over a receiver, a generalization of -- getChanContents where getChanContents = fold (:). -- Note that the type of fold implies that the folding function -- needs to be sufficiently non-strict, otherwise the result cannot be -- productive. fold :: (a -> b -> b) -> ReceivePort a -> IO b