-- 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 -- | -- -- 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) -- | -- -- 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. -- -- -- -- 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