-- 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:
--
--
-- - Program behavior can be more finely constrained via the type
-- system.
-- - 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.
--
--
-- 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:
--
--
-- - split-channel is restricted to in-process communications
-- only.
-- - split-channel has no restriction on the type of values
-- that may be communicated.
-- - There is a quasi-duality between the two approaches: Cloud
-- Haskell's ReceivePorts are special whereas
-- split-channel's SendPorts are special.
-- - ReceivePorts can be duplicated, which
-- allows for considerably more efficient publish-subscribe
-- communications than supported by Cloud Haskell at the present
-- time.
--
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