-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Cloud Haskell Extras
--
-- Supporting library, providing common types and utilities used by the
-- various libraries built on top of distributed-process
@package distributed-process-extras
@version 0.3.0
-- | If you don't know exactly what this module is for and precisely how to
-- use the types within, you should move on, quickly!
module Control.Distributed.Process.Extras.Internal.Unsafe
data PCopy a
-- | Wrap any Typeable datum in a PCopy. We hide the
-- constructor to discourage arbitrary uses of the type, since
-- PCopy is a specialised and potentially dangerous construct.
pCopy :: (Typeable a) => a -> PCopy a
-- | Matches on PCopy m and returns the m within. This
-- potentially allows us to bypass serialization (and the type
-- constraints it enforces) for local message passing (i.e., with
-- UnencodedMessage data), since PCopy is just a shim.
matchP :: (Typeable m) => Match (Maybe m)
-- | Matches on a TypedChannel (PCopy a).
matchChanP :: (Typeable m) => ReceivePort (PCopy m) -> Match m
-- | Given a raw Message, attempt to unwrap a Typeable
-- datum from an enclosing PCopy wrapper.
pUnwrap :: (Typeable m) => Message -> Process (Maybe m)
-- | A generic input channel that can be read from in the same fashion as a
-- typed channel (i.e., ReceivePort). To read from an input
-- stream in isolation, see readInputStream. To compose an
-- InputStream with reads on a process' mailbox (and/or typed
-- channels), see matchInputStream.
data InputStream a
Null :: InputStream a
-- | Create a new InputStream.
newInputStream :: forall a. (Typeable a) => Either (ReceivePort a) (STM a) -> InputStream a
-- | Constructs a Match for a given InputChannel.
matchInputStream :: InputStream a -> Match a
-- | Read from an InputStream. This is a blocking operation.
readInputStream :: (Serializable a) => InputStream a -> Process a
data InvalidBinaryShim
InvalidBinaryShim :: InvalidBinaryShim
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Unsafe.NullInputStream
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Unsafe.NullInputStream
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Unsafe.NullInputStream
instance GHC.Generics.Generic (Control.Distributed.Process.Extras.Internal.Unsafe.PCopy a)
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Unsafe.InvalidBinaryShim
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Unsafe.InvalidBinaryShim
instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Control.Distributed.Process.Extras.Internal.Unsafe.PCopy a)
instance Data.Typeable.Internal.Typeable a => Data.Binary.Class.Binary (Control.Distributed.Process.Extras.Internal.Unsafe.PCopy a)
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Unsafe.NullInputStream
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Unsafe.NullInputStream
-- | Types used throughout the Extras package
module Control.Distributed.Process.Extras.Internal.Types
-- | Tags provide uniqueness for messages, so that they can be matched with
-- their response.
type Tag = Int
-- | Generates unique Tag for messages and response pairs. Each
-- process that depends, directly or indirectly, on the call mechanisms
-- in Control.Distributed.Process.Global.Call should have at most
-- one TagPool on which to draw unique message tags.
type TagPool = MVar Tag
-- | Create a new per-process source of unique message identifiers.
newTagPool :: Process TagPool
-- | Extract a new identifier from a TagPool.
getTag :: TagPool -> Process Tag
-- | Class of things to which a Process can link itself.
class Linkable a where linkTo r = resolve r >>= traverse_ link
-- | Create a link with the supplied object.
linkTo :: (Linkable a, Resolvable a) => a -> Process ()
-- | Class of things that can be killed (or instructed to exit).
class Killable p where killProc r s = resolve r >>= traverse_ (flip kill $ s) exitProc r m = resolve r >>= traverse_ (flip exit $ m)
-- | Kill (instruct to exit) generic process, using kill primitive.
killProc :: (Killable p, Resolvable p) => p -> String -> Process ()
-- | Kill (instruct to exit) generic process, using exit primitive.
exitProc :: (Killable p, Resolvable p, Serializable m) => p -> m -> Process ()
-- | Class of things that can be resolved to a ProcessId.
class Resolvable a where unresolvableMessage = baseAddressableErrorMessage
-- | Resolve the reference to a process id, or Nothing if
-- resolution fails
resolve :: Resolvable a => a -> Process (Maybe ProcessId)
-- | Unresolvable Addressable Message
unresolvableMessage :: (Resolvable a, Resolvable a) => a -> String
-- | Class of things that you can route/send serializable message to
class Routable a where sendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> send p m) mPid } unsafeSendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> unsafeSend p $!! m) mPid }
-- | Send a message to the target asynchronously
sendTo :: (Routable a, Serializable m, Resolvable a) => a -> m -> Process ()
-- | Send some NFData message to the target asynchronously,
-- forcing evaluation (i.e., deepseq) beforehand.
unsafeSendTo :: (Routable a, NFSerializable m, Resolvable a) => a -> m -> Process ()
class (Resolvable a, Routable a) => Addressable a
-- | A simple means of mapping to a receiver.
data Recipient
Pid :: !ProcessId -> Recipient
Registered :: !String -> Recipient
RemoteRegistered :: !String -> !NodeId -> Recipient
-- | Used internally in whereisOrStart. Sent as (RegisterSelf,ProcessId).
data RegisterSelf
RegisterSelf :: RegisterSelf
-- | A synchronous version of whereis, this relies on call to
-- perform the relevant monitoring of the remote node.
whereisRemote :: NodeId -> String -> Process (Maybe ProcessId)
-- | resolve the Resolvable or die with specified msg plus details of what
-- didn't resolve
resolveOrDie :: (Resolvable a) => a -> String -> Process ProcessId
-- | Wait cancellation message.
data CancelWait
CancelWait :: CancelWait
-- | Simple representation of a channel.
type Channel a = (SendPort a, ReceivePort a)
-- | A ubiquitous shutdown signal that can be used to maintain a
-- consistent shutdown/stop protocol for any process that wishes to
-- handle it.
data Shutdown
Shutdown :: Shutdown
-- | Provides a reason for process termination.
data ExitReason
-- | indicates normal exit
ExitNormal :: ExitReason
-- | normal response to a Shutdown
ExitShutdown :: ExitReason
-- | abnormal (error) shutdown
ExitOther :: !String -> ExitReason
-- | Given when a server is unobtainable.
data ServerDisconnected
ServerDisconnected :: !DiedReason -> ServerDisconnected
-- | Introduces a class that brings NFData into scope along with
-- Serializable, such that we can force evaluation. Intended for use with
-- the UnsafePrimitives module (which wraps
-- Control.Distributed.Process.UnsafePrimitives), and guarantees
-- evaluatedness in terms of NFData. Please note that we
-- cannot guarantee that an NFData instance will behave
-- the same way as a Binary one with regards evaluation, so it
-- is still possible to introduce unexpected behaviour by using
-- unsafe primitives in this way.
class (NFData a, Serializable a) => NFSerializable a
__remoteTable :: RemoteTable -> RemoteTable
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.ServerDisconnected
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Types.Recipient
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Types.Recipient
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.Recipient
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Types.ExitReason
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Types.ExitReason
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.ExitReason
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Types.Shutdown
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Types.Shutdown
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.Shutdown
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.RegisterSelf
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Internal.Types.CancelWait
instance GHC.Show.Show Control.Distributed.Process.Extras.Internal.Types.CancelWait
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Internal.Types.CancelWait
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.CancelWait
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.CancelWait
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.RegisterSelf
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.RegisterSelf
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.Shutdown
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.Shutdown
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.ExitReason
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.ExitReason
instance Control.Distributed.Process.Extras.Internal.Types.Resolvable Control.Distributed.Process.Internal.Types.ProcessId
instance Control.Distributed.Process.Extras.Internal.Types.Resolvable GHC.Base.String
instance Control.Distributed.Process.Extras.Internal.Types.Resolvable (Control.Distributed.Process.Internal.Types.NodeId, GHC.Base.String)
instance Control.Distributed.Process.Extras.Internal.Types.Routable Control.Distributed.Process.Internal.Types.ProcessId
instance Control.Distributed.Process.Extras.Internal.Types.Routable GHC.Base.String
instance Control.Distributed.Process.Extras.Internal.Types.Routable (Control.Distributed.Process.Internal.Types.NodeId, GHC.Base.String)
instance Control.Distributed.Process.Extras.Internal.Types.Routable (Control.Distributed.Process.Internal.Types.Message -> Control.Distributed.Process.Internal.Types.Process ())
instance Control.Distributed.Process.Extras.Internal.Types.Addressable Control.Distributed.Process.Internal.Types.ProcessId
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.Recipient
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.Recipient
instance Control.Distributed.Process.Extras.Internal.Types.Resolvable Control.Distributed.Process.Extras.Internal.Types.Recipient
instance Control.Distributed.Process.Extras.Internal.Types.Routable Control.Distributed.Process.Extras.Internal.Types.Recipient
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Internal.Types.ServerDisconnected
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Internal.Types.ServerDisconnected
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable Control.Distributed.Process.Internal.Types.ProcessId
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable a => Control.Distributed.Process.Extras.Internal.Types.NFSerializable (Control.Distributed.Process.Internal.Types.SendPort a)
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable Control.Distributed.Process.Internal.Types.Message
-- | This module provides facilities for working with time delays and
-- timeouts. The type Timeout and the timeout family of
-- functions provide mechanisms for working with
-- threadDelay-like behaviour that operates on microsecond
-- values.
--
-- The TimeInterval and TimeUnit related functions provide
-- an abstraction for working with various time intervals, whilst the
-- Delay type provides a corrolary to timeout that works
-- with these.
module Control.Distributed.Process.Extras.Time
-- | given a number, produces a TimeInterval of microseconds
microSeconds :: Int -> TimeInterval
-- | given a number, produces a TimeInterval of milliseconds
milliSeconds :: Int -> TimeInterval
-- | given a number, produces a TimeInterval of seconds
seconds :: Int -> TimeInterval
-- | given a number, produces a TimeInterval of minutes
minutes :: Int -> TimeInterval
-- | given a number, produces a TimeInterval of hours
hours :: Int -> TimeInterval
-- | converts the supplied TimeInterval to microseconds
asTimeout :: TimeInterval -> Int
-- | Convenience for making timeouts; e.g.,
--
--
-- receiveTimeout (after 3 Seconds) [ match (\"ok" -> return ()) ]
--
after :: Int -> TimeUnit -> Int
-- | Convenience for making TimeInterval; e.g.,
--
--
-- let ti = within 5 Seconds in .....
--
within :: Int -> TimeUnit -> TimeInterval
-- | converts the supplied TimeUnit to microseconds
timeToMicros :: TimeUnit -> Int -> Int
-- | A time interval.
data TimeInterval
-- | Defines the time unit for a Timeout value
data TimeUnit
Days :: TimeUnit
Hours :: TimeUnit
Minutes :: TimeUnit
Seconds :: TimeUnit
Millis :: TimeUnit
Micros :: TimeUnit
-- | Represents either a delay of TimeInterval, an infinite wait or
-- no delay (i.e., non-blocking).
data Delay
Delay :: TimeInterval -> Delay
Infinity :: Delay
NoDelay :: Delay
-- | given a TimeInterval, provide an equivalent
-- NominalDiffTim
timeIntervalToDiffTime :: TimeInterval -> NominalDiffTime
-- | given a NominalDiffTim, provide an equivalent
-- TimeInterval@
diffTimeToTimeInterval :: NominalDiffTime -> TimeInterval
-- | given a NominalDiffTim, provide an equivalent Delay@
diffTimeToDelay :: NominalDiffTime -> Delay
-- | given a Delay, provide an equivalent NominalDiffTim
delayToDiffTime :: Delay -> NominalDiffTime
-- | Create a NominalDiffTime from a number of microseconds.
microsecondsToNominalDiffTime :: Integer -> NominalDiffTime
-- | Represents a timeout in terms of microseconds, where
-- Nothing stands for infinity and Just 0, no-delay.
type Timeout = Maybe Int
-- | Send to a process when a timeout expires.
data TimeoutNotification
TimeoutNotification :: Tag -> TimeoutNotification
-- | Sends the calling process TimeoutNotification tag after
-- time microseconds
timeout :: Int -> Tag -> ProcessId -> Process ()
-- | Constructs an inifinite Timeout.
infiniteWait :: Timeout
-- | Constructs a no-wait Timeout
noWait :: Timeout
instance GHC.Show.Show Control.Distributed.Process.Extras.Time.Delay
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Time.Delay
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Time.Delay
instance GHC.Show.Show Control.Distributed.Process.Extras.Time.TimeInterval
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Time.TimeInterval
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Time.TimeInterval
instance GHC.Show.Show Control.Distributed.Process.Extras.Time.TimeUnit
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Time.TimeUnit
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Time.TimeUnit
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Time.TimeUnit
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Time.TimeUnit
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Time.TimeInterval
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Time.TimeInterval
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Time.Delay
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Time.Delay
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Time.TimeoutNotification
instance GHC.Num.Num Control.Distributed.Process.Extras.Time.TimeInterval
instance GHC.Num.Num Control.Distributed.Process.Extras.Time.Delay
-- |
-- - Unsafe Messaging Primitives Using NFData
--
--
-- This module mirrors
-- Control.Distributed.Process.UnsafePrimitives, but attempts to
-- provide a bit more safety by forcing evaluation before sending. This
-- is handled using NFData, by means of the
-- NFSerializable type class.
--
-- Note that we still cannot guarantee that both the
-- NFData and Binary instances will evaluate your data
-- the same way, therefore these primitives still have certain risks and
-- potential side effects. Use with caution.
module Control.Distributed.Process.Extras.UnsafePrimitives
send :: NFSerializable m => ProcessId -> m -> Process ()
nsend :: NFSerializable a => String -> a -> Process ()
sendToAddr :: (Addressable a, NFSerializable m) => a -> m -> Process ()
sendChan :: (NFSerializable m) => SendPort m -> m -> Process ()
-- | Create an unencoded Message for any Serializable
-- type.
wrapMessage :: NFSerializable a => a -> Message
-- | Provides an API for running code or sending messages, either after
-- some initial delay or periodically, and for cancelling, re-setting
-- and/or flushing pending timers.
module Control.Distributed.Process.Extras.Timer
-- | an opaque reference to a timer
type TimerRef = ProcessId
-- | represents a tick event that timers can generate
data Tick
Tick :: Tick
-- | blocks the calling Process for the specified TimeInterval. Note that
-- this function assumes that a blocking receive is the most efficient
-- approach to acheiving this, however the runtime semantics
-- (particularly with regards scheduling) should not differ from
-- threadDelay in practise.
sleep :: TimeInterval -> Process ()
-- | Literate way of saying sleepFor 3 Seconds.
sleepFor :: Int -> TimeUnit -> Process ()
-- | starts a timer which sends the supplied message to the destination
-- process after the specified time interval.
sendAfter :: (NFSerializable a) => TimeInterval -> ProcessId -> a -> Process TimerRef
-- | runs the supplied process action(s) after t has elapsed
runAfter :: TimeInterval -> Process () -> Process TimerRef
-- | calls exit pid reason after t has elapsed
exitAfter :: (Serializable a) => TimeInterval -> ProcessId -> a -> Process TimerRef
-- | kills the specified process after t has elapsed
killAfter :: TimeInterval -> ProcessId -> String -> Process TimerRef
-- | starts a timer that repeatedly sends the supplied message to the
-- destination process each time the specified time interval elapses. To
-- stop messages from being sent in future, cancelTimer can be
-- called.
startTimer :: (NFSerializable a) => TimeInterval -> ProcessId -> a -> Process TimerRef
-- | sets up a timer that sends Tick repeatedly at intervals of
-- t
ticker :: TimeInterval -> ProcessId -> Process TimerRef
-- | runs the supplied process action(s) repeatedly at intervals of
-- t
periodically :: TimeInterval -> Process () -> Process TimerRef
-- | resets a running timer. Note: Cancelling a timer does not guarantee
-- that all its messages are prevented from being delivered to the target
-- process. Also note that resetting an ongoing timer (started using the
-- startTimer or periodically functions) will only cause
-- the current elapsed period to time out, after which the timer will
-- continue running. To stop a long-running timer permanently, you should
-- use cancelTimer instead.
resetTimer :: TimerRef -> Process ()
-- | permanently cancels a timer
cancelTimer :: TimerRef -> Process ()
-- | cancels a running timer and flushes any viable timer messages from the
-- process' message queue. This function should only be called by the
-- process expecting to receive the timer's messages!
flushTimer :: (Serializable a, Eq a) => TimerRef -> a -> Delay -> Process ()
instance GHC.Show.Show Control.Distributed.Process.Extras.Timer.SleepingPill
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Timer.SleepingPill
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Timer.SleepingPill
instance GHC.Show.Show Control.Distributed.Process.Extras.Timer.Tick
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Timer.Tick
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Timer.Tick
instance GHC.Show.Show Control.Distributed.Process.Extras.Timer.TimerConfig
instance GHC.Classes.Eq Control.Distributed.Process.Extras.Timer.TimerConfig
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Timer.TimerConfig
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Timer.TimerConfig
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Timer.TimerConfig
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable Control.Distributed.Process.Extras.Timer.TimerConfig
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Timer.Tick
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Timer.Tick
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable Control.Distributed.Process.Extras.Timer.Tick
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Timer.SleepingPill
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Timer.SleepingPill
-- | A simple FIFO queue implementation backed by Data.Sequence.
module Control.Distributed.Process.Extras.Internal.Queue.SeqQ
data SeqQ a
empty :: SeqQ a
isEmpty :: SeqQ a -> Bool
singleton :: a -> SeqQ a
enqueue :: SeqQ a -> a -> SeqQ a
dequeue :: SeqQ a -> Maybe (a, SeqQ a)
peek :: SeqQ a -> Maybe a
instance GHC.Show.Show a => GHC.Show.Show (Control.Distributed.Process.Extras.Internal.Queue.SeqQ.SeqQ a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Control.Distributed.Process.Extras.Internal.Queue.SeqQ.SeqQ a)
module Control.Distributed.Process.Extras.Internal.Queue.PriorityQ
newtype PriorityQ k a
PriorityQ :: PQueue k a -> PriorityQ k a
[q] :: PriorityQ k a -> PQueue k a
empty :: Ord k => PriorityQ k v
isEmpty :: Ord k => PriorityQ k v -> Bool
singleton :: Ord k => k -> a -> PriorityQ k a
enqueue :: Ord k => k -> v -> PriorityQ k v -> PriorityQ k v
dequeue :: Ord k => PriorityQ k v -> Maybe (v, PriorityQ k v)
peek :: Ord k => PriorityQ k v -> Maybe v
-- | Maintainers : Jeff Epstein, Tim Watson Stability : experimental
-- Portability : non-portable (requires concurrency)
--
-- This module provides a set of additional primitives that add
-- functionality to the basic Cloud Haskell APIs.
module Control.Distributed.Process.Extras.Internal.Primitives
class (Resolvable a, Routable a) => Addressable a
-- | Class of things that you can route/send serializable message to
class Routable a where sendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> send p m) mPid } unsafeSendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> unsafeSend p $!! m) mPid }
-- | Send a message to the target asynchronously
sendTo :: (Routable a, Serializable m, Resolvable a) => a -> m -> Process ()
-- | Send some NFData message to the target asynchronously,
-- forcing evaluation (i.e., deepseq) beforehand.
unsafeSendTo :: (Routable a, NFSerializable m, Resolvable a) => a -> m -> Process ()
-- | Class of things that can be resolved to a ProcessId.
class Resolvable a where unresolvableMessage = baseAddressableErrorMessage
-- | Resolve the reference to a process id, or Nothing if
-- resolution fails
resolve :: Resolvable a => a -> Process (Maybe ProcessId)
-- | Unresolvable Addressable Message
unresolvableMessage :: (Resolvable a, Resolvable a) => a -> String
-- | Class of things to which a Process can link itself.
class Linkable a where linkTo r = resolve r >>= traverse_ link
-- | Create a link with the supplied object.
linkTo :: (Linkable a, Resolvable a) => a -> Process ()
-- | Class of things that can be killed (or instructed to exit).
class Killable p where killProc r s = resolve r >>= traverse_ (flip kill $ s) exitProc r m = resolve r >>= traverse_ (flip exit $ m)
-- | Kill (instruct to exit) generic process, using kill primitive.
killProc :: (Killable p, Resolvable p) => p -> String -> Process ()
-- | Kill (instruct to exit) generic process, using exit primitive.
exitProc :: (Killable p, Resolvable p, Serializable m) => p -> m -> Process ()
-- | Spawn a new (local) process. This variant takes an initialisation
-- action and a secondary expression from the result of the
-- initialisation to Process (). The spawn operation
-- synchronises on the completion of the before action, such
-- that the calling process is guaranteed to only see the newly spawned
-- ProcessId once the initialisation has successfully completed.
spawnSignalled :: Process a -> (a -> Process ()) -> Process ProcessId
-- | Node local version of spawnLink. Note that this is just the
-- sequential composition of spawn and link. (The
-- Unified semantics that underlies Cloud Haskell does not even
-- support a synchronous link operation)
spawnLinkLocal :: Process () -> Process ProcessId
-- | Like spawnLinkLocal, but monitors the spawned process.
spawnMonitorLocal :: Process () -> Process (ProcessId, MonitorRef)
-- | CH's link primitive, unlike Erlang's, will trigger when the
-- target process dies for any reason. This function has semantics like
-- Erlang's: it will trigger ProcessLinkException only when the
-- target dies abnormally.
linkOnFailure :: ProcessId -> Process ()
-- | A synchronous version of whereis, this relies on call to
-- perform the relevant monitoring of the remote node.
whereisRemote :: NodeId -> String -> Process (Maybe ProcessId)
-- | Returns the pid of the process that has been registered under the
-- given name. This refers to a local, per-node registration, not
-- global registration. If that name is unregistered, a process
-- is started. This is a handy way to start per-node named servers.
whereisOrStart :: String -> Process () -> Process ProcessId
-- | A remote equivalent of whereisOrStart. It deals with the node
-- registry on the given node, and the process, if it needs to be
-- started, will run on that node. If the node is inaccessible, Nothing
-- will be returned.
whereisOrStartRemote :: NodeId -> String -> Closure (Process ()) -> Process (Maybe ProcessId)
-- | An alternative to matchIf that allows both predicate and action
-- to be expressed in one parameter.
matchCond :: (Serializable a) => (a -> Maybe (Process b)) -> Match b
-- | Safe (i.e., monitored) waiting on an expected response/message.
awaitResponse :: Addressable a => a -> [Match (Either ExitReason b)] -> Process (Either ExitReason b)
-- | Apply the supplied expression n times
times :: Int -> Process () -> Process ()
-- | Monitor any Resolvable object.
monitor :: Resolvable a => a -> Process (Maybe MonitorRef)
awaitExit :: Resolvable a => a -> Process ()
isProcessAlive :: ProcessId -> Process Bool
-- | Like forever but sans space leak
forever' :: Monad m => m a -> m b
deliver :: (Addressable a, Serializable m) => m -> a -> Process ()
__remoteTable :: RemoteTable -> RemoteTable
module Control.Distributed.Process.Extras.Internal.Containers.MultiMap
-- | Opaque type of MultiMaps.
data MultiMap k v
-- | Class of things that can be inserted in a map or a set (of mapped
-- values), for which instances of Eq and Hashable must
-- be present.
class (Eq a, Hashable a) => Insertable a
empty :: MultiMap k v
insert :: forall k v. (Insertable k, Insertable v) => k -> v -> MultiMap k v -> MultiMap k v
member :: (Insertable k) => k -> MultiMap k a -> Bool
lookup :: (Insertable k) => k -> MultiMap k v -> Maybe [v]
filter :: forall k v. (Insertable k) => (v -> Bool) -> MultiMap k v -> MultiMap k v
filterWithKey :: forall k v. (Insertable k) => (k -> v -> Bool) -> MultiMap k v -> MultiMap k v
toList :: MultiMap k v -> [(k, v)]
instance (GHC.Classes.Eq a, Data.Hashable.Class.Hashable a) => Control.Distributed.Process.Extras.Internal.Containers.MultiMap.Insertable a
instance Data.Foldable.Foldable (Control.Distributed.Process.Extras.Internal.Containers.MultiMap.MultiMap k)
-- |
-- - Cloud Haskell Extras
-- - Evaluation Strategies and Support for NFData
--
--
-- When sending messages to a local process (i.e., intra-node), the
-- default approach is to encode (i.e., serialise) the message
-- anyway, just to ensure that no unevaluated thunks are passed to
-- the receiver. In distributed-process, you must explicitly choose to
-- use unsafe primitives that do nothing to ensure evaluation,
-- since this might cause an error in the receiver which would be
-- difficult to debug. Using NFData, it is possible to force
-- evaluation, but there is no way to ensure that both the
-- NFData and Binary instances do so in the same way
-- (i.e., to the same depth, etc) therefore automatic use of
-- NFData is not possible in distributed-process.
--
-- By contrast, distributed-process-platform makes extensive use of
-- NFData to force evaluation (and avoid serialisation overheads
-- during intra-node communication), via the NFSerializable type
-- class. This does nothing to fix the potential disparity between
-- NFData and Binary instances, so you should verify
-- that your data is being handled as expected (e.g., by sticking to
-- strict fields, or some such) and bear in mind that things could go
-- wrong.
--
-- The UnsafePrimitives module in this library will force
-- evaluation before calling the UnsafePrimitives in
-- distributed-process, which - if you've vetted everything correctly -
-- should provide a bit more safety, whilst still keeping performance at
-- an acceptable level.
--
-- Users of the various service and utility models (such as
-- ManagedProcess and the Service and Task
-- APIs) should consult the sub-system specific documentation for
-- instructions on how to utilise these features.
--
-- IMPORTANT NOTICE: Despite the apparent safety of forcing evaluation
-- before sending, we still cannot make any actual guarantees
-- about the evaluation semantics of these operations, and therefore the
-- unsafe moniker will remain in place, in one form or another,
-- for all functions and modules that use them.
--
--
-- - Error/Exception Handling
--
--
-- It is important not to be too general when catching exceptions
-- in cloud haskell application, because asynchonous exceptions provide
-- cloud haskell with its process termination mechanism. Two exception
-- types in particular, signal the instigator's intention to stop a
-- process immediately, which are raised (i.e., thrown) in response to
-- the kill and exit primitives provided by the base
-- distributed-process package.
--
-- You should generally try to keep exception handling code to the lowest
-- (i.e., most specific) scope possible. If you wish to trap
-- exit signals, use the various flavours of catchExit
-- primitive from distributed-process.
module Control.Distributed.Process.Extras
class (Resolvable a, Routable a) => Addressable a
-- | Class of things that can be resolved to a ProcessId.
class Resolvable a where unresolvableMessage = baseAddressableErrorMessage
-- | Resolve the reference to a process id, or Nothing if
-- resolution fails
resolve :: Resolvable a => a -> Process (Maybe ProcessId)
-- | Unresolvable Addressable Message
unresolvableMessage :: (Resolvable a, Resolvable a) => a -> String
-- | Class of things that you can route/send serializable message to
class Routable a where sendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> send p m) mPid } unsafeSendTo a m = do { mPid <- resolve a; maybe (die (unresolvableMessage a)) (\ p -> unsafeSend p $!! m) mPid }
-- | Send a message to the target asynchronously
sendTo :: (Routable a, Serializable m, Resolvable a) => a -> m -> Process ()
-- | Send some NFData message to the target asynchronously,
-- forcing evaluation (i.e., deepseq) beforehand.
unsafeSendTo :: (Routable a, NFSerializable m, Resolvable a) => a -> m -> Process ()
-- | Class of things to which a Process can link itself.
class Linkable a where linkTo r = resolve r >>= traverse_ link
-- | Create a link with the supplied object.
linkTo :: (Linkable a, Resolvable a) => a -> Process ()
-- | Class of things that can be killed (or instructed to exit).
class Killable p where killProc r s = resolve r >>= traverse_ (flip kill $ s) exitProc r m = resolve r >>= traverse_ (flip exit $ m)
-- | Kill (instruct to exit) generic process, using kill primitive.
killProc :: (Killable p, Resolvable p) => p -> String -> Process ()
-- | Kill (instruct to exit) generic process, using exit primitive.
exitProc :: (Killable p, Resolvable p, Serializable m) => p -> m -> Process ()
-- | Introduces a class that brings NFData into scope along with
-- Serializable, such that we can force evaluation. Intended for use with
-- the UnsafePrimitives module (which wraps
-- Control.Distributed.Process.UnsafePrimitives), and guarantees
-- evaluatedness in terms of NFData. Please note that we
-- cannot guarantee that an NFData instance will behave
-- the same way as a Binary one with regards evaluation, so it
-- is still possible to introduce unexpected behaviour by using
-- unsafe primitives in this way.
class (NFData a, Serializable a) => NFSerializable a
-- | A simple means of mapping to a receiver.
data Recipient
Pid :: !ProcessId -> Recipient
Registered :: !String -> Recipient
RemoteRegistered :: !String -> !NodeId -> Recipient
-- | A ubiquitous shutdown signal that can be used to maintain a
-- consistent shutdown/stop protocol for any process that wishes to
-- handle it.
data Shutdown
Shutdown :: Shutdown
-- | Provides a reason for process termination.
data ExitReason
-- | indicates normal exit
ExitNormal :: ExitReason
-- | normal response to a Shutdown
ExitShutdown :: ExitReason
-- | abnormal (error) shutdown
ExitOther :: !String -> ExitReason
-- | Wait cancellation message.
data CancelWait
CancelWait :: CancelWait
-- | Given when a server is unobtainable.
data ServerDisconnected
ServerDisconnected :: !DiedReason -> ServerDisconnected
-- | Simple representation of a channel.
type Channel a = (SendPort a, ReceivePort a)
-- | Tags provide uniqueness for messages, so that they can be matched with
-- their response.
type Tag = Int
-- | Generates unique Tag for messages and response pairs. Each
-- process that depends, directly or indirectly, on the call mechanisms
-- in Control.Distributed.Process.Global.Call should have at most
-- one TagPool on which to draw unique message tags.
type TagPool = MVar Tag
-- | Monitor any Resolvable object.
monitor :: Resolvable a => a -> Process (Maybe MonitorRef)
-- | Spawn a new (local) process. This variant takes an initialisation
-- action and a secondary expression from the result of the
-- initialisation to Process (). The spawn operation
-- synchronises on the completion of the before action, such
-- that the calling process is guaranteed to only see the newly spawned
-- ProcessId once the initialisation has successfully completed.
spawnSignalled :: Process a -> (a -> Process ()) -> Process ProcessId
-- | Node local version of spawnLink. Note that this is just the
-- sequential composition of spawn and link. (The
-- Unified semantics that underlies Cloud Haskell does not even
-- support a synchronous link operation)
spawnLinkLocal :: Process () -> Process ProcessId
-- | Like spawnLinkLocal, but monitors the spawned process.
spawnMonitorLocal :: Process () -> Process (ProcessId, MonitorRef)
-- | CH's link primitive, unlike Erlang's, will trigger when the
-- target process dies for any reason. This function has semantics like
-- Erlang's: it will trigger ProcessLinkException only when the
-- target dies abnormally.
linkOnFailure :: ProcessId -> Process ()
-- | Apply the supplied expression n times
times :: Int -> Process () -> Process ()
isProcessAlive :: ProcessId -> Process Bool
-- | An alternative to matchIf that allows both predicate and action
-- to be expressed in one parameter.
matchCond :: (Serializable a) => (a -> Maybe (Process b)) -> Match b
deliver :: (Addressable a, Serializable m) => m -> a -> Process ()
awaitExit :: Resolvable a => a -> Process ()
-- | Safe (i.e., monitored) waiting on an expected response/message.
awaitResponse :: Addressable a => a -> [Match (Either ExitReason b)] -> Process (Either ExitReason b)
-- | Create a new per-process source of unique message identifiers.
newTagPool :: Process TagPool
-- | Extract a new identifier from a TagPool.
getTag :: TagPool -> Process Tag
-- | Returns the pid of the process that has been registered under the
-- given name. This refers to a local, per-node registration, not
-- global registration. If that name is unregistered, a process
-- is started. This is a handy way to start per-node named servers.
whereisOrStart :: String -> Process () -> Process ProcessId
-- | A remote equivalent of whereisOrStart. It deals with the node
-- registry on the given node, and the process, if it needs to be
-- started, will run on that node. If the node is inaccessible, Nothing
-- will be returned.
whereisOrStartRemote :: NodeId -> String -> Closure (Process ()) -> Process (Maybe ProcessId)
__remoteTable :: RemoteTable -> RemoteTable
-- | Maintainers : Jeff Epstein, Tim Watson Stability : experimental
-- Portability : non-portable (requires concurrency)
--
-- This module provides a facility for Remote Procedure Call (rpc) style
-- interactions with Cloud Haskell processes.
--
-- Clients make synchronous calls to a running process (i.e., server)
-- using the callAt, callTimeout and multicall
-- functions. Processes acting as the server are constructed using Cloud
-- Haskell's receive family of primitives and the
-- callResponse family of functions in this module.
module Control.Distributed.Process.Extras.Call
-- | Like callTimeout, but with no timeout. Returns Nothing if the
-- target process dies.
callAt :: (Serializable a, Serializable b) => ProcessId -> a -> Tag -> Process (Maybe b)
-- | Sends a message of type a to the given process, to be handled by a
-- corresponding callResponse... function, which will send back a message
-- of type b. The tag is per-process unique identifier of the
-- transaction. If the timeout expires or the target process dies,
-- Nothing will be returned.
callTimeout :: (Serializable a, Serializable b) => ProcessId -> a -> Tag -> Timeout -> Process (Maybe b)
-- | Like callTimeout, but sends the message to multiple recipients
-- and collects the results.
multicall :: forall a b. (Serializable a, Serializable b) => [ProcessId] -> a -> Tag -> Timeout -> Process [Maybe b]
-- | Produces a Match that can be used with the receiveWait family
-- of message-receiving functions. callResponse will respond to
-- a message of type a sent by callTimeout, and will respond with
-- a value of type b.
callResponse :: (Serializable a, Serializable b) => (a -> Process (b, c)) -> Match c
callResponseIf :: (Serializable a, Serializable b) => (a -> Bool) -> (a -> Process (b, c)) -> Match c
callResponseDefer :: (Serializable a, Serializable b) => (a -> (b -> Process ()) -> Process c) -> Match c
callResponseDeferIf :: (Serializable a, Serializable b) => (a -> Bool) -> (a -> (b -> Process ()) -> Process c) -> Match c
-- | Produces a Match that can be used with the receiveWait family
-- of message-receiving functions. When calllForward receives a message
-- of type from from callTimeout (and similar), it will forward
-- the message to another process, who will be responsible for responding
-- to it. It is the user's responsibility to ensure that the forwarding
-- process is linked to the destination process, so that if it fails, the
-- sender will be notified.
callForward :: Serializable a => (a -> (ProcessId, c)) -> Match c
-- | The message handling code is started in a separate thread. It's not
-- automatically linked to the calling thread, so if you want it to be
-- terminated when the message handling thread dies, you'll need to call
-- link yourself.
callResponseAsync :: (Serializable a, Serializable b) => (a -> Maybe c) -> (a -> Process b) -> Match c
instance GHC.Classes.Eq a => GHC.Classes.Eq (Control.Distributed.Process.Extras.Call.MulticallResponseType a)
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Call.Multicall
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Call.MulticallResponse
-- | This module provides a primitive node monitoring capability,
-- implemented as a distributed-process Management Agent. Once the
-- nodeMonitor agent is started, calling monitorNodes will
-- ensure that whenever the local node detects a new network-transport
-- connection (from another cloud haskell node), the caller will receive
-- a NodeUp message in its mailbox. If a node disconnects, a
-- corollary NodeDown message will be delivered as well.
module Control.Distributed.Process.Extras.Monitoring
-- | Sent to subscribing processes when a connection (from a remote node)
-- is detected.
data NodeUp
NodeUp :: !NodeId -> NodeUp
-- | Sent to subscribing processes when a dis-connection (from a remote
-- node) is detected.
data NodeDown
NodeDown :: !NodeId -> NodeDown
-- | The MxAgentId for the node monitoring agent.
nodeMonitorAgentId :: MxAgentId
-- | Starts the node monitoring agent. No call to monitorNodes and
-- unmonitorNodes will have any effect unless the agent is
-- already running. Note that we make no guarantees what-so-ever
-- about the timeliness or ordering semantics of node monitoring
-- notifications.
nodeMonitor :: Process ProcessId
-- | Start monitoring node connection/disconnection events. When a
-- connection event occurs, the calling process will receive a message
-- NodeUp NodeId in its mailbox. When a disconnect occurs, the
-- corollary NodeDown NodeId message will be delivered instead.
--
-- No guaranatee is made about the timeliness of the delivery, nor can
-- the receiver expect that the node (for which it is being notified) is
-- still upconnected or downdisconnected at the point when it
-- receives a message from the node monitoring agent.
monitorNodes :: Process ()
-- | Stop monitoring node connection/disconnection events. This does not
-- flush the caller's mailbox, nor does it guarantee that any/all node
-- up/down notifications will have been delivered before it is evaluated.
unmonitorNodes :: Process ()
instance GHC.Show.Show Control.Distributed.Process.Extras.Monitoring.NodeDown
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Monitoring.NodeDown
instance GHC.Show.Show Control.Distributed.Process.Extras.Monitoring.NodeUp
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Monitoring.NodeUp
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Monitoring.UnRegister
instance GHC.Generics.Generic Control.Distributed.Process.Extras.Monitoring.Register
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Monitoring.Register
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Monitoring.Register
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Monitoring.UnRegister
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Monitoring.UnRegister
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Monitoring.NodeUp
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Monitoring.NodeUp
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.Monitoring.NodeDown
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.Monitoring.NodeDown
-- | This module provides a general purpose logging facility, implemented
-- as a distributed-process Management Agent. To start the logging
-- agent on a running node, evaluate systemLog with the relevant
-- expressions to handle logging textual messages, a cleanup operation
-- (if required), initial log level and a formatting expression.
--
-- We export a working example in the form of systemLogFile, which
-- logs to a text file using buffered I/O. Its implementation is very
-- simple, and should serve as a demonstration of how to use the API:
--
--
-- systemLogFile :: FilePath -> LogLevel -> LogFormat -> Process ProcessId
-- systemLogFile path lvl fmt = do
-- h <- liftIO $ openFile path AppendMode
-- liftIO $ hSetBuffering h LineBuffering
-- systemLog (liftIO . hPutStrLn h) (liftIO (hClose h)) lvl fmt
--
module Control.Distributed.Process.Extras.SystemLog
data LogLevel
Debug :: LogLevel
Info :: LogLevel
Notice :: LogLevel
Warning :: LogLevel
Error :: LogLevel
Critical :: LogLevel
Alert :: LogLevel
Emergency :: LogLevel
type LogFormat = String -> Process String
data LogClient
data LogChan
type LogText = String
class ToLog m where toLog = return . LogData . unsafeWrapMessage
toLog :: (ToLog m, Serializable m) => m -> Process (LogLevel -> LogMessage)
class Logger a
logMessage :: Logger a => a -> LogMessage -> Process ()
mxLogId :: MxAgentId
-- | Start a system logger process as a management agent.
systemLog :: (String -> Process ()) -> (Process ()) -> LogLevel -> LogFormat -> Process ProcessId
client :: Process (Maybe LogClient)
logChannel :: LogChan
addFormatter :: (Addressable r) => r -> Closure (Message -> Process (Maybe String)) -> Process ()
-- | Start a system logger that writes to a file.
--
-- This is a very basic file logging facility, that uses
-- regular buffered file I/O (i.e., System.IO.hPutStrLn
-- et al) under the covers. The handle is closed appropriately if/when
-- the logging process terminates.
--
-- See
-- Control.Distributed.Process.Management.mxAgentWithFinalize
-- for futher details about management agents that use finalizers.
systemLogFile :: FilePath -> LogLevel -> LogFormat -> Process ProcessId
report :: (Logger l) => (l -> LogText -> Process ()) -> l -> String -> Process ()
debug :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
info :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
notice :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
warning :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
error :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
critical :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
alert :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
emergency :: (Logger l, Serializable m, ToLog m) => l -> m -> Process ()
sendLog :: (Logger l, Serializable m, ToLog m) => l -> m -> LogLevel -> Process ()
instance GHC.Show.Show Control.Distributed.Process.Extras.SystemLog.LogMessage
instance GHC.Generics.Generic Control.Distributed.Process.Extras.SystemLog.LogMessage
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.SystemLog.AddFormatter
instance GHC.Generics.Generic Control.Distributed.Process.Extras.SystemLog.AddFormatter
instance GHC.Generics.Generic Control.Distributed.Process.Extras.SystemLog.SetLevel
instance GHC.Enum.Enum Control.Distributed.Process.Extras.SystemLog.LogLevel
instance GHC.Classes.Ord Control.Distributed.Process.Extras.SystemLog.LogLevel
instance GHC.Show.Show Control.Distributed.Process.Extras.SystemLog.LogLevel
instance GHC.Read.Read Control.Distributed.Process.Extras.SystemLog.LogLevel
instance GHC.Classes.Eq Control.Distributed.Process.Extras.SystemLog.LogLevel
instance GHC.Generics.Generic Control.Distributed.Process.Extras.SystemLog.LogLevel
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.SystemLog.LogLevel
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.SystemLog.LogLevel
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.SystemLog.SetLevel
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.SystemLog.SetLevel
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.SystemLog.AddFormatter
instance Data.Binary.Class.Binary Control.Distributed.Process.Extras.SystemLog.LogMessage
instance Control.DeepSeq.NFData Control.Distributed.Process.Extras.SystemLog.LogMessage
instance Control.Distributed.Process.Extras.Internal.Types.Routable Control.Distributed.Process.Extras.SystemLog.LogChan
instance Control.Distributed.Process.Extras.Internal.Types.NFSerializable Control.Distributed.Process.Extras.SystemLog.LogText
instance Control.Distributed.Process.Extras.Internal.Types.Resolvable Control.Distributed.Process.Extras.SystemLog.LogClient
instance Control.Distributed.Process.Extras.Internal.Types.Routable Control.Distributed.Process.Extras.SystemLog.LogClient
instance Control.Distributed.Process.Extras.SystemLog.ToLog Control.Distributed.Process.Extras.SystemLog.LogText
instance Control.Distributed.Process.Extras.SystemLog.ToLog Control.Distributed.Process.Internal.Types.Message
instance Control.Distributed.Process.Extras.SystemLog.Logger Control.Distributed.Process.Extras.SystemLog.LogClient
instance Control.Distributed.Process.Extras.SystemLog.Logger Control.Distributed.Process.Extras.SystemLog.LogChan
module Control.Concurrent.Utils
-- | Opaque lock.
data Lock
-- | Create exclusive lock. Only one process could take such lock.
mkExclusiveLock :: IO Lock
-- | Create quantity lock. A fixed number of processes can take this lock
-- simultaniously.
mkQLock :: Int -> IO Lock
-- | Run action under a held lock.
withLock :: (MonadMask m, MonadIO m) => Lock -> m a -> m a