-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Concurrency library in the style of Erlang/OTP
--   
--   Minimalistic actor library inspired by Erlang/OTP with support for
--   supervisor hierarchies and asynchronous messages, as well as
--   abstractions for synchronous communication and easy management of TCP
--   connections.
@package nqe
@version 0.6.1


-- | This is the core of the NQE library. It is composed of code to deal
--   with processes and mailboxes. Processes represent concurrent threads
--   that receive messages via a mailbox, also referred to as a channel.
--   NQE is inspired by Erlang/OTP and it stands for “Not Quite Erlang”. A
--   process is analogous to an actor in Scala, or an object in the
--   original (Alan Kay) sense of the word. To implement synchronous
--   communication NQE makes use of <a>STM</a> actions embedded in
--   asynchronous messages.
module Control.Concurrent.NQE.Process

-- | <a>STM</a> function that receives an event and does something with it.
type Listen a = a -> STM ()

-- | Channel that only allows messages to be sent to it.
data Mailbox msg
Mailbox :: !mbox msg -> !Unique -> Mailbox msg

-- | Channel that allows to send or receive messages.
data Inbox msg
Inbox :: !mbox msg -> !Unique -> Inbox msg

-- | <a>Async</a> handle and <a>Mailbox</a> for a process.
data Process msg
Process :: Async () -> Mailbox msg -> Process msg
[getProcessAsync] :: Process msg -> Async ()
[getProcessMailbox] :: Process msg -> Mailbox msg

-- | Class for implementation of an <a>Inbox</a>.
class InChan mbox

-- | Are there messages queued?
mailboxEmptySTM :: InChan mbox => mbox msg -> STM Bool

-- | Receive a message.
receiveSTM :: InChan mbox => mbox msg -> STM msg

-- | Put a message in the mailbox such that it is received next.
requeueSTM :: InChan mbox => msg -> mbox msg -> STM ()

-- | Class for implementation of a <a>Mailbox</a>.
class OutChan mbox

-- | Is this bounded channel full? Always <a>False</a> for unbounded
--   channels.
mailboxFullSTM :: OutChan mbox => mbox msg -> STM Bool

-- | Send a message to this channel.
sendSTM :: OutChan mbox => msg -> mbox msg -> STM ()

-- | Get a send-only <a>Mailbox</a> for an <a>Inbox</a>.
inboxToMailbox :: Inbox msg -> Mailbox msg

-- | Wrap a channel in an <a>Inbox</a>
wrapChannel :: (MonadIO m, InChan mbox, OutChan mbox) => mbox msg -> m (Inbox msg)

-- | Create an unbounded <a>Inbox</a>.
newInbox :: MonadIO m => m (Inbox msg)

-- | <a>Inbox</a> with upper bound on number of allowed queued messages.
newBoundedInbox :: MonadIO m => Natural -> m (Inbox msg)

-- | Send a message to a channel.
send :: (MonadIO m, OutChan mbox) => msg -> mbox msg -> m ()

-- | Receive a message from a channel.
receive :: (InChan mbox, MonadIO m) => mbox msg -> m msg

-- | Send request to channel and wait for a response. The <tt>request</tt>
--   <a>STM</a> action will be created by this function.
query :: (MonadIO m, OutChan mbox) => (Listen response -> request) -> mbox request -> m response

-- | Do a <a>query</a> but timeout after <tt>u</tt> microseconds. Return
--   <a>Nothing</a> if timeout reached.
queryU :: (MonadUnliftIO m, OutChan mbox) => Int -> (Listen response -> request) -> mbox request -> m (Maybe response)

-- | Do a <a>query</a> but timeout after <tt>s</tt> seconds. Return
--   <a>Nothing</a> if timeout reached.
queryS :: (MonadUnliftIO m, OutChan mbox) => Int -> (Listen response -> request) -> mbox request -> m (Maybe response)

-- | Test all messages in a channel against the supplied function and
--   return the first matching message. Will block until a match is found.
--   Messages that do not match remain in the channel.
receiveMatch :: (MonadIO m, InChan mbox) => mbox msg -> (msg -> Maybe a) -> m a

-- | Like <a>receiveMatch</a> but with a timeout set at <tt>u</tt>
--   microseconds. Returns <a>Nothing</a> if timeout is reached.
receiveMatchU :: (MonadUnliftIO m, InChan mbox) => Int -> mbox msg -> (msg -> Maybe a) -> m (Maybe a)

-- | Like <a>receiveMatch</a> but with a timeout set at <tt>s</tt> seconds.
--   Returns <a>Nothing</a> if timeout is reached.
receiveMatchS :: (MonadUnliftIO m, InChan mbox) => Int -> mbox msg -> (msg -> Maybe a) -> m (Maybe a)

-- | Match a message in the channel as an atomic <a>STM</a> action.
receiveMatchSTM :: InChan mbox => mbox msg -> (msg -> Maybe a) -> STM a

-- | Check if the channel is empty.
mailboxEmpty :: (MonadIO m, InChan mbox) => mbox msg -> m Bool

-- | Put a list of messages at the start of a channel, so that the last
--   element of the list is the next message to be received.
requeueListSTM :: InChan mbox => [msg] -> mbox msg -> STM ()

-- | Run a process in the background and pass it to a function. Stop the
--   background process once the function returns. Background process
--   exceptions are re-thrown in the current thread.
withProcess :: MonadUnliftIO m => (Inbox msg -> m ()) -> (Process msg -> m a) -> m a

-- | Run a process in the background and return the <a>Process</a> handle.
--   Background process exceptions are re-thrown in the current thread.
process :: MonadUnliftIO m => (Inbox msg -> m ()) -> m (Process msg)

-- | Create an unbounded inbox and corresponding mailbox.
newMailbox :: MonadUnliftIO m => m (Inbox msg, Mailbox msg)
instance GHC.Classes.Eq (Control.Concurrent.NQE.Process.Process msg)
instance Control.Concurrent.NQE.Process.OutChan Control.Concurrent.NQE.Process.Process
instance Data.Hashable.Class.Hashable (Control.Concurrent.NQE.Process.Process msg)
instance GHC.Classes.Eq (Control.Concurrent.NQE.Process.Mailbox msg)
instance Control.Concurrent.NQE.Process.OutChan Control.Concurrent.NQE.Process.Mailbox
instance Data.Hashable.Class.Hashable (Control.Concurrent.NQE.Process.Mailbox msg)
instance GHC.Classes.Eq (Control.Concurrent.NQE.Process.Inbox msg)
instance Control.Concurrent.NQE.Process.InChan Control.Concurrent.NQE.Process.Inbox
instance Control.Concurrent.NQE.Process.OutChan Control.Concurrent.NQE.Process.Inbox
instance Control.Concurrent.NQE.Process.OutChan Control.Concurrent.STM.TQueue.TQueue
instance Control.Concurrent.NQE.Process.OutChan Control.Concurrent.STM.TBQueue.TBQueue
instance Control.Concurrent.NQE.Process.InChan Control.Concurrent.STM.TQueue.TQueue
instance Control.Concurrent.NQE.Process.InChan Control.Concurrent.STM.TBQueue.TBQueue


-- | Mix NQE processes with conduits for easy concurrent IO.
module Control.Concurrent.NQE.Conduit

-- | Consumes messages from a <a>Conduit</a> and sends them to a channel.
conduitMailbox :: (MonadIO m, OutChan mbox, Typeable msg) => mbox msg -> ConduitT msg o m ()


-- | A publisher is a process that forwards messages to subscribers. NQE
--   publishers are simple, and do not implement filtering directly,
--   although that can be done on the <a>STM</a> <a>Listen</a> actions that
--   forward messages to subscribers.
--   
--   If a subscriber has been added to a publisher using the
--   <a>subscribe</a> function, it needs to be removed later using
--   <a>unsubscribe</a> when it is no longer needed, or the publisher will
--   continue calling its <a>Listen</a> action in the future, likely
--   causing memory leaks.
module Control.Concurrent.NQE.Publisher

-- | Handle of a subscriber to a process. Should be kept in order to
--   unsubscribe.
data Subscriber msg

-- | Messages that a publisher will take.
data PublisherMessage msg
Subscribe :: !Listen msg -> !Listen (Subscriber msg) -> PublisherMessage msg
Unsubscribe :: !Subscriber msg -> PublisherMessage msg
Event :: msg -> PublisherMessage msg

-- | Alias for a publisher process.
type Publisher msg = Process (PublisherMessage msg)

-- | Create a mailbox, subscribe it to a publisher and pass it to the
--   supplied function . End subscription when function returns.
withSubscription :: MonadUnliftIO m => Publisher msg -> (Inbox msg -> m a) -> m a

-- | <a>Listen</a> to events from a publisher.
subscribe :: MonadIO m => Publisher msg -> Listen msg -> m (Subscriber msg)

-- | Stop listening to events from a publisher. Must provide
--   <a>Subscriber</a> that was returned from corresponding
--   <a>subscribe</a> action.
unsubscribe :: MonadIO m => Publisher msg -> Subscriber msg -> m ()

-- | Start a publisher in the background and pass it to a function. The
--   publisher will be stopped when the function function returns.
withPublisher :: MonadUnliftIO m => (Publisher msg -> m a) -> m a

-- | Start a publisher in the background.
publisher :: MonadUnliftIO m => m (Publisher msg)

-- | Start a publisher in the current thread.
publisherProcess :: MonadUnliftIO m => Inbox (PublisherMessage msg) -> m ()
instance GHC.Classes.Eq (Control.Concurrent.NQE.Publisher.Subscriber msg)
instance Data.Hashable.Class.Hashable (Control.Concurrent.NQE.Publisher.Subscriber msg)


-- | Supervisors run and monitor processes, including other supervisors. A
--   supervisor has a corresponding <a>Strategy</a> that controls its
--   behaviour if a child stops. Supervisors deal with exceptions in
--   concurrent processes so that their code does not need to be written in
--   an overly-defensive style. They help prevent problems caused by
--   processes dying quietly in the background, potentially locking an
--   entire application.
module Control.Concurrent.NQE.Supervisor

-- | Alias for child action to be executed asynchronously by supervisor.
type ChildAction = IO ()

-- | Thread handler for child.
type Child = Async ()

-- | Send this message to a supervisor to add or remove a child.
data SupervisorMessage

-- | Alias for supervisor process.
type Supervisor = Process SupervisorMessage

-- | Supervisor strategies to decide what to do when a child stops.
data Strategy

-- | send a <tt>SupervisorNotif</tt> to <a>Mailbox</a> when child dies
Notify :: Listen (Child, Maybe SomeException) -> Strategy

-- | kill all processes and propagate exception upstream
KillAll :: Strategy

-- | ignore processes that stop without raising an exception
IgnoreGraceful :: Strategy

-- | keep running if a child dies and ignore it
IgnoreAll :: Strategy

-- | Run a supervisor asynchronously and pass its mailbox to a function.
--   Supervisor will be stopped along with all its children when the
--   function ends.
withSupervisor :: MonadUnliftIO m => Strategy -> (Supervisor -> m a) -> m a

-- | Run a supervisor as an asynchronous process.
supervisor :: MonadUnliftIO m => Strategy -> m Supervisor

-- | Run a supervisor in the current thread.
supervisorProcess :: MonadUnliftIO m => Strategy -> Inbox SupervisorMessage -> m ()

-- | Add a new <a>ChildAction</a> to the supervisor. Will return the
--   <a>Child</a> that was just started. This function will not block or
--   raise an exception if the child dies.
addChild :: MonadIO m => Supervisor -> ChildAction -> m Child

-- | Stop a <a>Child</a> controlled by this supervisor. Will block until
--   the child dies.
removeChild :: MonadIO m => Supervisor -> Child -> m ()


-- | Concurrency library inspired by Erlang/OTP.
module NQE
