-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | The Cloud Haskell Application Platform -- -- Modelled after Erlang OTP's gen_server, this framework provides -- similar facilities for Cloud Haskell, grouping essential practices for -- client/server development into a set of modules and standards designed -- to help you build concurrent, distributed applications with relative -- ease. @package distributed-process-client-server @version 0.1.2 -- | Unsafe variant of the Managed Process Client API. This module -- implements the client portion of a Managed Process using the unsafe -- variants of cloud haskell's messaging primitives. It relies on the -- -extras implementation of UnsafePrimitives, which forces -- evaluation for types that provide an NFData instance. Direct -- use of the underlying unsafe primitives (from the distributed-process -- library) without NFData instances is unsupported. -- -- IMPORTANT NOTE: As per the platform documentation, it is not possible -- to guarantee that an NFData instance will force -- evaluation in the same way that a Binary instance would (when -- encoding to a byte string). Please read the unsafe primitives -- documentation carefully and make sure you know what you're doing. You -- have been warned. -- -- See Control.Distributed.Process.Extras. See -- Control.Distributed.Process.Extras.UnsafePrimitives. See -- Control.Distributed.Process.UnsafePrimitives. module Control.Distributed.Process.ManagedProcess.UnsafeClient -- | Send a control message over a ControlPort. This version of -- shutdown uses unsafe primitives. sendControlMessage :: Serializable m => ControlPort m -> m -> Process () -- | Send a signal instructing the process to terminate. This version of -- shutdown uses unsafe primitives. shutdown :: ProcessId -> Process () -- | Make a synchronous call - uses unsafe primitives. call :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process b -- | Safe version of call that returns information about the error -- if the operation fails - uses unsafe primitives. safeCall :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process (Either ExitReason b) -- | Version of safeCall that returns Nothing if the -- operation fails. Uses unsafe primitives. tryCall :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process (Maybe b) -- | Make a synchronous call, but timeout and return Nothing if a -- reply is not received within the specified time interval - uses -- unsafe primitives. callTimeout :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> TimeInterval -> Process (Maybe b) flushPendingCalls :: NFSerializable b => TimeInterval -> (b -> Process b) -> Process (Maybe b) -- | Invokes call out of band, and returns an "async handle." -- Uses unsafe primitives. callAsync :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process (Async b) -- | Sends a cast message to the server identified by -- server - uses unsafe primitives. cast :: (Addressable a, NFSerializable m) => a -> m -> Process () -- | Sends a channel message to the server and returns a -- ReceivePort - uses unsafe primitives. callChan :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process (ReceivePort b) syncCallChan :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process b syncSafeCallChan :: (Addressable s, NFSerializable a, NFSerializable b) => s -> a -> Process (Either ExitReason b) module Control.Distributed.Process.ManagedProcess.Server.Priority prioritiseCall :: (Serializable a, Serializable b) => (s -> a -> Priority b) -> DispatchPriority s prioritiseCall_ :: (Serializable a, Serializable b) => (a -> Priority b) -> DispatchPriority s prioritiseCast :: Serializable a => (s -> a -> Priority ()) -> DispatchPriority s prioritiseCast_ :: Serializable a => (a -> Priority ()) -> DispatchPriority s prioritiseInfo :: Serializable a => (s -> a -> Priority ()) -> DispatchPriority s prioritiseInfo_ :: Serializable a => (a -> Priority ()) -> DispatchPriority s setPriority :: Int -> Priority m -- | The Server Portion of the Managed Process API. module Control.Distributed.Process.ManagedProcess.Server -- | Creates a Condition from a function that takes a process state -- a and an input message b and returns a Bool -- indicating whether the associated handler should run. condition :: (Serializable a, Serializable b) => (a -> b -> Bool) -> Condition a b -- | Create a Condition from a function that takes a process state -- a and returns a Bool indicating whether the associated -- handler should run. state :: Serializable m => (s -> Bool) -> Condition s m -- | Creates a Condition from a function that takes an input message -- m and returns a Bool indicating whether the associated -- handler should run. input :: Serializable m => (m -> Bool) -> Condition s m -- | Instructs the process to send a reply and continue running. reply :: Serializable r => r -> s -> Process (ProcessReply r s) -- | Instructs the process to send a reply and evaluate the -- ProcessAction. replyWith :: Serializable r => r -> ProcessAction s -> Process (ProcessReply r s) -- | Instructs the process to skip sending a reply and evaluate a -- ProcessAction noReply :: Serializable r => ProcessAction s -> Process (ProcessReply r s) -- | Instructs the process to continue running and receiving messages. continue :: s -> Process (ProcessAction s) -- | Instructs the process loop to wait for incoming messages until -- Delay is exceeded. If no messages are handled during this -- period, the timeout handler will be called. Note that this -- alters the process timeout permanently such that the given -- Delay will remain in use until changed. timeoutAfter :: Delay -> s -> Process (ProcessAction s) -- | Instructs the process to hibernate for the given -- TimeInterval. Note that no messages will be removed from the -- mailbox until after hibernation has ceased. This is equivalent to -- calling threadDelay. hibernate :: TimeInterval -> s -> Process (ProcessAction s) -- | Instructs the process to terminate, giving the supplied reason. If a -- valid shutdownHandler is installed, it will be called with the -- ExitReason returned from this call, along with the process -- state. stop :: ExitReason -> Process (ProcessAction s) -- | As stop, but provides an updated state for the shutdown -- handler. stopWith :: s -> ExitReason -> Process (ProcessAction s) -- | Sends a reply explicitly to a caller. -- --
--   replyTo = sendTo
--   
replyTo :: Serializable m => CallRef m -> m -> Process () -- | Sends a reply to a SendPort (for use in handleRpcChan et -- al). -- --
--   replyChan = sendChan
--   
replyChan :: Serializable m => SendPort m -> m -> Process () -- | Continue without giving a reply to the caller - equivalent to -- continue, but usable in a callback passed to the -- handleCall family of functions. noReply_ :: Serializable r => s -> Process (ProcessReply r s) -- | Halt process execution during a call handler, without paying any -- attention to the expected return type. haltNoReply_ :: Serializable r => ExitReason -> Process (ProcessReply r s) -- | Version of continue that can be used in handlers that ignore -- process state. continue_ :: s -> Process (ProcessAction s) -- | Version of timeoutAfter that can be used in handlers that -- ignore process state. -- --
--   action (\(TimeoutPlease duration) -> timeoutAfter_ duration)
--   
timeoutAfter_ :: Delay -> (s -> Process (ProcessAction s)) -- | Version of hibernate that can be used in handlers that ignore -- process state. -- --
--   action (\(HibernatePlease delay) -> hibernate_ delay)
--   
hibernate_ :: TimeInterval -> (s -> Process (ProcessAction s)) -- | Version of stop that can be used in handlers that ignore -- process state. -- --
--   action (\ClientError -> stop_ ExitNormal)
--   
stop_ :: ExitReason -> (s -> Process (ProcessAction s)) -- | Constructs a call handler from a function in the -- Process monad. > handleCall = handleCallIf (const True) handleCall :: (Serializable a, Serializable b) => (s -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Constructs a call handler from an ordinary function in the -- Process monad. Given a function f :: (s -> a -> -- Process (ProcessReply b s)), the expression handleCall f -- will yield a Dispatcher for inclusion in a Behaviour -- specification for the GenProcess. Messages are only dispatched -- to the handler if the supplied condition evaluates to True. handleCallIf :: (Serializable a, Serializable b) => Condition s a -> (s -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | As handleCall but passes the CallRef to the handler -- function. This can be useful if you wish to reply later to the -- caller by, e.g., spawning a process to do some work and have it -- replyTo caller response out of band. In this case the -- callback can pass the CallRef to the worker (or stash it away -- itself) and return noReply. handleCallFrom :: (Serializable a, Serializable b) => (s -> CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | As handleCallFrom but only runs the handler if the supplied -- Condition evaluates to True. handleCallFromIf :: (Serializable a, Serializable b) => Condition s a -> (s -> CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Creates a handler for a typed channel RPC style interaction. -- The handler takes a SendPort b to reply to, the initial input -- and evaluates to a ProcessAction. It is the handler code's -- responsibility to send the reply to the SendPort. handleRpcChan :: (Serializable a, Serializable b) => (s -> SendPort b -> a -> Process (ProcessAction s)) -> Dispatcher s -- | As handleRpcChan, but only evaluates the handler if the -- supplied condition is met. handleRpcChanIf :: (Serializable a, Serializable b) => Condition s a -> (s -> SendPort b -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Constructs a cast handler from an ordinary function in the -- Process monad. > handleCast = handleCastIf (const True) handleCast :: Serializable a => (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Constructs a cast handler from an ordinary function in the -- Process monad. Given a function f :: (s -> a -> -- Process (ProcessAction s)), the expression handleCall f -- will yield a Dispatcher for inclusion in a Behaviour -- specification for the GenProcess. handleCastIf :: Serializable a => Condition s a -> (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Creates a generic input handler (i.e., for received messages that are -- not sent using the cast or call APIs) from an -- ordinary function in the Process monad. handleInfo :: Serializable a => (s -> a -> Process (ProcessAction s)) -> DeferredDispatcher s -- | Handle completely raw input messages. handleRaw :: (s -> Message -> Process (ProcessAction s)) -> DeferredDispatcher s -- | Constructs a handler for both call and cast messages. -- handleDispatch = handleDispatchIf (const True) handleDispatch :: Serializable a => (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Constructs a handler for both call and cast messages. -- Messages are only dispatched to the handler if the supplied condition -- evaluates to True. Handlers defined in this way have no -- access to the call context (if one exists) and cannot therefore reply -- to calls. handleDispatchIf :: Serializable a => Condition s a -> (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Creates an exit handler scoped to the execution of any and all -- the registered call, cast and info handlers for the process. handleExit :: Serializable a => (s -> ProcessId -> a -> Process (ProcessAction s)) -> ExitSignalDispatcher s handleExitIf :: Serializable a => (s -> a -> Bool) -> (s -> ProcessId -> a -> Process (ProcessAction s)) -> ExitSignalDispatcher s -- | Constructs an action handler. Like handleDispatch this -- can handle both cast and call messages, but you -- won't know which you're dealing with. This can be useful where certain -- inputs require a definite action, such as stopping the server, without -- concern for the state (e.g., when stopping we need only decide to -- stop, as the terminate handler can deal with state cleanup etc). For -- example: -- --
--   action (MyCriticalSignal -> stop_ ExitNormal)
--   
action :: Serializable a => (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Constructs a call handler from a function in the -- Process monad. The handler expression returns the reply, and -- the action will be set to continue. -- --
--   handleCall_ = handleCallIf_ $ input (const True)
--   
handleCall_ :: (Serializable a, Serializable b) => (a -> Process b) -> Dispatcher s -- | Constructs a call handler from an ordinary function in the -- Process monad. This variant ignores the state argument present -- in handleCall and handleCallIf and is therefore useful -- in a stateless server. Messges are only dispatched to the handler if -- the supplied condition evaluates to True -- -- See handleCall handleCallIf_ :: (Serializable a, Serializable b) => Condition s a -> (a -> Process b) -> Dispatcher s -- | A variant of handleCallFrom_ that ignores the state argument. handleCallFrom_ :: (Serializable a, Serializable b) => (CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | A variant of handleCallFromIf that ignores the state argument. handleCallFromIf_ :: (Serializable a, Serializable b) => (Condition s a) -> (CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | A variant of handleRpcChan that ignores the state argument. handleRpcChan_ :: (Serializable a, Serializable b) => (SendPort b -> a -> Process (ProcessAction ())) -> Dispatcher () -- | A variant of handleRpcChanIf that ignores the state argument. handleRpcChanIf_ :: (Serializable a, Serializable b) => Condition () a -> (SendPort b -> a -> Process (ProcessAction ())) -> Dispatcher () -- | Version of handleCast that ignores the server state. handleCast_ :: Serializable a => (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Version of handleCastIf that ignores the server state. handleCastIf_ :: Serializable a => Condition s a -> (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Constructs a control channel handler from a function in the -- Process monad. The handler expression returns no reply, and the -- control message is treated in the same fashion as a -- cast. -- --
--   handleControlChan = handleControlChanIf $ input (const True)
--   
handleControlChan :: Serializable a => ControlChannel a -> (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Version of handleControlChan that ignores the server state. handleControlChan_ :: Serializable a => ControlChannel a -> (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | A safe variant of the Server Portion of the Managed -- Process API. Most of these operations have the same names as -- similar operations in the impure Server module (re-exported -- by the primary API in ManagedProcess). To remove the -- ambiguity, some combination of either qualification and/or the -- hiding clause will be required. -- -- -- -- The idea behind this module is to provide safe callbacks, i.e., -- server code that is free from side effects. This safety is enforced by -- the type system via the RestrictedProcess monad. A StateT -- interface is provided for code running in the -- RestrictedProcess monad, so that server side state can be -- managed safely without resorting to IO (or code running in the -- Process monad). module Control.Distributed.Process.ManagedProcess.Server.Restricted -- | Restricted (i.e., pure, free from side effects) execution environment -- for callcastinfo handlers to execute in. data RestrictedProcess s a -- | The result of a call handler's execution. data Result a -- | reply with the given term Reply :: a -> Result a -- | reply with the given term and enter timeout Timeout :: Delay -> a -> Result a -- | reply with the given term and hibernate Hibernate :: TimeInterval -> a -> Result a -- | stop the process with the given reason Stop :: ExitReason -> Result a -- | The result of a safe cast handler's execution. data RestrictedAction -- | continue executing RestrictedContinue :: RestrictedAction -- | timeout if no messages are received RestrictedTimeout :: Delay -> RestrictedAction -- | hibernate (i.e., sleep) RestrictedHibernate :: TimeInterval -> RestrictedAction -- | stop/terminate the server process RestrictedStop :: ExitReason -> RestrictedAction -- | A version of -- "Control.Distributed.Process.ManagedProcess.Server.handleCall" that -- takes a handler which executes in RestrictedProcess. handleCall :: (Serializable a, Serializable b) => (a -> RestrictedProcess s (Result b)) -> Dispatcher s -- | A version of -- "Control.Distributed.Process.ManagedProcess.Server.handleCallIf" that -- takes a handler which executes in RestrictedProcess. handleCallIf :: (Serializable a, Serializable b) => (Condition s a) -> (a -> RestrictedProcess s (Result b)) -> Dispatcher s -- | A version of -- "Control.Distributed.Process.ManagedProcess.Server.handleCast" that -- takes a handler which executes in RestrictedProcess. handleCast :: Serializable a => (a -> RestrictedProcess s RestrictedAction) -> Dispatcher s -- | A version of -- "Control.Distributed.Process.ManagedProcess.Server.handleCastIf" that -- takes a handler which executes in RestrictedProcess. handleCastIf :: Serializable a => Condition s a -> (a -> RestrictedProcess s RestrictedAction) -> Dispatcher s -- | A version of -- "Control.Distributed.Process.ManagedProcess.Server.handleInfo" that -- takes a handler which executes in RestrictedProcess. handleInfo :: Serializable a => (a -> RestrictedProcess s RestrictedAction) -> DeferredDispatcher s handleExit :: Serializable a => (a -> RestrictedProcess s RestrictedAction) -> ExitSignalDispatcher s handleTimeout :: (Delay -> RestrictedProcess s RestrictedAction) -> TimeoutHandler s -- | Put a new process state state putState :: s -> RestrictedProcess s () -- | Get the current process state getState :: RestrictedProcess s s -- | Apply the given expression to the current process state modifyState :: (s -> s) -> RestrictedProcess s () -- | Instructs the process to send a reply and continue running. reply :: Serializable r => r -> RestrictedProcess s (Result r) -- | Continue without giving a reply to the caller - equivalent to -- continue, but usable in a callback passed to the -- handleCall family of functions. noReply :: Serializable r => Result r -> RestrictedProcess s (Result r) -- | Halt process execution during a call handler, without paying any -- attention to the expected return type. haltNoReply :: Serializable r => ExitReason -> RestrictedProcess s (Result r) -- | Instructs the process to continue running and receiving messages. continue :: RestrictedProcess s RestrictedAction -- | Instructs the process loop to wait for incoming messages until -- Delay is exceeded. If no messages are handled during this -- period, the timeout handler will be called. Note that this -- alters the process timeout permanently such that the given -- Delay will remain in use until changed. timeoutAfter :: Delay -> RestrictedProcess s RestrictedAction -- | Instructs the process to hibernate for the given -- TimeInterval. Note that no messages will be removed from the -- mailbox until after hibernation has ceased. This is equivalent to -- evaluating liftIO . threadDelay. hibernate :: TimeInterval -> RestrictedProcess s RestrictedAction -- | Instructs the process to terminate, giving the supplied reason. If a -- valid shutdownHandler is installed, it will be called with the -- ExitReason returned from this call, along with the process -- state. stop :: ExitReason -> RestrictedProcess s RestrictedAction -- | Log a trace message using the underlying Process's say say :: String -> RestrictedProcess s () instance Typeable RestrictedProcess instance Typeable Result instance Functor (RestrictedProcess s) instance Monad (RestrictedProcess s) instance MonadState s (RestrictedProcess s) instance MonadIO (RestrictedProcess s) instance Applicative (RestrictedProcess s) -- | The Client Portion of the Managed Process API. module Control.Distributed.Process.ManagedProcess.Client -- | Send a control message over a ControlPort. sendControlMessage :: Serializable m => ControlPort m -> m -> Process () -- | Send a signal instructing the process to terminate. The receive -- loop which manages the process mailbox will prioritise -- Shutdown signals higher than any other incoming messages, but -- the server might be busy (i.e., still in the process of excuting a -- handler) at the time of sending however, so the caller should not make -- any assumptions about the timeliness with which the shutdown signal -- will be handled. If responsiveness is important, a better approach -- might be to send an exit signal with Shutdown as the -- reason. An exit signal will interrupt any operation currently underway -- and force the running process to clean up and terminate. shutdown :: ProcessId -> Process () -- | Make a synchronous call - will block until a reply is received. The -- calling process will exit with ExitReason if the calls fails. call :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process b -- | Safe version of call that returns information about the error -- if the operation fails. If an error occurs then the explanation will -- be will be stashed away as (ExitOther String). safeCall :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process (Either ExitReason b) -- | Version of safeCall that returns Nothing if the -- operation fails. If you need information about *why* a call has failed -- then you should use safeCall or combine catchExit and -- call instead. tryCall :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process (Maybe b) -- | Make a synchronous call, but timeout and return Nothing if a -- reply is not received within the specified time interval. -- -- If the result of the call is a failure (or the call was cancelled) -- then the calling process will exit, with the ExitReason given -- as the reason. If the call times out however, the semantics on the -- server side are undefined, i.e., the server may or may not -- successfully process the request and may (or may not) send a response -- at a later time. From the callers perspective, this is somewhat -- troublesome, since the call result cannot be decoded directly. In this -- case, the flushPendingCalls API may be used to attempt -- to receive the message later on, however this makes no attempt -- whatsoever to guarantee which call response will in fact be -- returned to the caller. In those semantics are unsuited to your -- application, you might choose to exit or die in case -- of a timeout, or alternatively, use the callAsync API and -- associated waitTimeout function (in the Async API), -- which takes a re-usable handle on which to wait (with timeouts) -- multiple times. callTimeout :: (Addressable s, Serializable a, Serializable b) => s -> a -> TimeInterval -> Process (Maybe b) flushPendingCalls :: Serializable b => TimeInterval -> (b -> Process b) -> Process (Maybe b) -- | Invokes call out of band, and returns an async -- handle. callAsync :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process (Async b) -- | Sends a cast message to the server identified by -- server. The server will not send a response. Like Cloud -- Haskell's send primitive, cast is fully asynchronous and -- never fails - therefore casting to a non-existent (e.g., -- dead) server process will not generate an error. cast :: (Addressable a, Serializable m) => a -> m -> Process () -- | Sends a channel message to the server and returns a -- ReceivePort on which the reponse can be delivered, if the -- server so chooses (i.e., the might ignore the request or crash). callChan :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process (ReceivePort b) -- | A synchronous version of callChan. syncCallChan :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process b -- | A safe version of syncCallChan, which returns Left -- ExitReason if the call fails. syncSafeCallChan :: (Addressable s, Serializable a, Serializable b) => s -> a -> Process (Either ExitReason b) -- | This module provides a high(er) level API for building complex -- Process implementations by abstracting out the management of -- the process' mailbox, reply/response handling, timeouts, process -- hiberation, error handling and shutdown/stop procedures. It is -- modelled along similar lines to OTP's gen_server API - -- http://www.erlang.org/doc/man/gen_server.html. -- -- In particular, a managed process will interoperate cleanly with -- the supervisor API in distributed-process-supervision. -- -- -- -- Once started, a managed process will consume messages from its -- mailbox and pass them on to user defined handlers based on the -- types received (mapped to those accepted by the handlers) and -- optionally by also evaluating user supplied predicates to determine -- which handler(s) should run. Each handler returns a -- ProcessAction which specifies how we should proceed. If none of -- the handlers is able to process a message (because their types are -- incompatible), then the unhandledMessagePolicy will be applied. -- -- The ProcessAction type defines the ways in which our process -- can respond to its inputs, whether by continuing to read incoming -- messages, setting an optional timeout, sleeping for a while or -- stopping. The optional timeout behaves a little differently to the -- other process actions. If no messages are received within the -- specified time span, a user defined timeoutHandler will be -- called in order to determine the next action. -- -- The ProcessDefinition type also defines a -- shutdownHandler, which is called whenever the process exits, -- whether because a callback has returned stop as the next -- action, or as the result of unhandled exit signal or similar -- asynchronous exceptions thrown in (or to) the process itself. -- -- The other handlers are split into two groups: apiHandlers and -- infoHandlers. The former contains handlers for the cast -- and call protocols, whilst the latter contains handlers that -- deal with input messages which are not sent via these API calls (i.e., -- messages sent using bare send or signals put into the process -- mailbox by the node controller, such as -- ProcessMonitorNotification and the like). -- -- -- -- Deliberate interactions with a managed process usually fall -- into one of two categories. A cast interaction involves a -- client sending a message asynchronously and the server handling this -- input. No reply is sent to the client. On the other hand, a -- call is a remote procedure call, where the client sends -- a message and waits for a reply from the server. -- -- All expressions given to apiHandlers have to conform to the -- cast|call protocol. The protocol (messaging) implementation is -- hidden from the user; API functions for creating user defined -- apiHandlers are given instead, which take expressions (i.e., -- a function or lambda expression) and create the appropriate -- Dispatcher for handling the cast (or call). -- -- These castcall protocols are for dealing with expected/ inputs. -- They will usually form the explicit public API for the process, and be -- exposed by providing module level functions that defer to the -- cast/call API, giving the author an opportunity to enforce the correct -- types. For example: -- --
--   {- Ask the server to add two numbers -}
--   add :: ProcessId -> Double -> Double -> Double
--   add pid x y = call pid (Add x y)
--   
-- -- Note here that the return type from the call is inferred and -- will not be enforced by the type system. If the server sent a -- different type back in the reply, then the caller might be blocked -- indefinitely! In fact, the result of mis-matching the expected return -- type (in the client facing API) with the actual type returned by the -- server is more severe in practise. The underlying types that implement -- the call protocol carry information about the expected return -- type. If there is a mismatch between the input and output types that -- the client API uses and those which the server declares it can handle, -- then the message will be considered unroutable - no handler will be -- executed against it and the unhandled message policy will be applied. -- You should, therefore, take great care to align these types since the -- default unhandled message policy is to terminate the server! That -- might seem pretty extreme, but you can alter the unhandled message -- policy and/or use the various overloaded versions of the call API in -- order to detect errors on the server such as this. -- -- The cost of potential type mismatches between the client and server is -- the main disadvantage of this looser coupling between them. This -- mechanism does however, allow servers to handle a variety of messages -- without specifying the entire protocol to be supported in excruciating -- detail. -- -- -- -- An explicit protocol for communicating with the process can be -- configured using cast and call, but it is not possible -- to prevent other kinds of messages from being sent to the process -- mailbox. When any message arrives for which there are no handlers able -- to process its content, the UnhandledMessagePolicy will be -- applied. Sometimes it is desireable to process incoming messages which -- aren't part of the protocol, rather than let the policy deal with -- them. This is particularly true when incoming messages are important -- to the process, but their point of origin is outside the author's -- control. Handling signals such as -- ProcessMonitorNotification is a typical example of this: -- --
--   handleInfo_ (\(ProcessMonitorNotification _ _ r) -> say $ show r >> continue_)
--   
-- -- -- -- The ProcessDefinition is parameterised by the type of state it -- maintains. A process that has no state will have the type -- ProcessDefinition () and can be bootstrapped by evaluating -- statelessProcess. -- -- All call/cast handlers come in two flavours, those which take the -- process state as an input and those which do not. Handlers that ignore -- the process state have to return a function that takes the state and -- returns the required action. Versions of the various action generating -- functions ending in an underscore are provided to simplify this: -- --
--   statelessProcess {
--       apiHandlers = [
--         handleCall_   (\(n :: Int) -> return (n * 2))
--       , handleCastIf_ (\(c :: String, _ :: Delay) -> c == "timeout")
--                       (\("timeout", (d :: Delay)) -> timeoutAfter_ d)
--       ]
--     , timeoutHandler = \_ _ -> stop $ ExitOther "timeout"
--   }
--   
-- -- -- -- If you wish to only write side-effect free code in your server -- definition, then there is an explicit API for doing so. Instead of -- using the handlers definition functions in this module, import the -- pure server module instead, which provides a StateT based monad -- for building referentially transparent callbacks. -- -- See -- Control.Distributed.Process.ManagedProcess.Server.Restricted -- for details and API documentation. -- -- -- -- Error handling appears in several contexts and process definitions can -- hook into these with relative ease. Only process failures as a result -- of asynchronous exceptions are supported by the API, which provides -- several scopes for error handling. -- -- Catching exceptions inside handler functions is no different to -- ordinary exception handling in monadic code. -- --
--   handleCall (\x y ->
--                catch (hereBeDragons x y)
--                      (\(e :: SmaugTheTerribleException) ->
--                           return (Left (show e))))
--   
-- -- The caveats mentioned in Control.Distributed.Process.Extras -- about exit signal handling obviously apply here as well. -- -- -- -- Because Control.Distributed.Process.ProcessExitException is a -- ubiquitous signalling mechanism in Cloud Haskell, it is treated unlike -- other asynchronous exceptions. The ProcessDefinition -- exitHandlers field accepts a list of handlers that, for a -- specific exit reason, can decide how the process should respond. If -- none of these handlers matches the type of reason then the -- process will exit with DiedException why. In addition, a -- private exit handler is installed for exit signals where -- reason :: ExitReason, which is a form of exit signal -- used explicitly by the supervision APIs. This behaviour, which cannot -- be overriden, is to gracefully shut down the process, calling the -- shutdownHandler as usual, before stopping with -- reason given as the final outcome. -- -- Example: handling custom data is ProcessExitException -- --
--   handleExit  (\state from (sigExit :: SomeExitData) -> continue s)
--   
-- -- Under some circumstances, handling exit signals is perfectly -- legitimate. Handling of other forms of asynchronous exception -- (e.g., exceptions not generated by an exit signal) is not -- supported by this API. Cloud Haskell's primitives for exception -- handling will work normally in managed process callbacks -- however. -- -- If any asynchronous exception goes unhandled, the process will -- immediately exit without running the shutdownHandler. It is -- very important to note that in Cloud Haskell, link failures generate -- asynchronous exceptions in the target and these will NOT be caught by -- the API and will therefore cause the process to exit without -- running the termination handler callback. If your termination -- handler is set up to do important work (such as resource cleanup) then -- you should avoid linking you process and use monitors instead. -- -- -- -- Many processes need to prioritise certain classes of message over -- others, so two subsets of the API are given to supporting those cases. -- -- A PrioritisedProcessDefintion combines the usual -- ProcessDefintion - containing the cast/call API, error, -- termination and info handlers - with a list of Priority -- entries, which are used at runtime to prioritise the server's inputs. -- Note that it is only messages which are prioritised; The server's -- various handlers are still evaluated in insertion order. -- -- Prioritisation does not guarantee that a prioritised message/type will -- be processed before other traffic - indeed doing so in a -- multi-threaded runtime would be very hard - but in the absence of -- races between multiple processes, if two messages are both present in -- the process' own mailbox, they will be applied to the -- ProcessDefinition's handler's in priority order. This is achieved by -- draining the real mailbox into a priority queue and processing each -- message in turn. -- -- A prioritised process must be configured with a Priority list -- to be of any use. Creating a prioritised process without any -- priorities would be a big waste of computational resources, and it is -- worth thinking carefully about whether or not prioritisation is truly -- necessary in your design before choosing to use it. -- -- Using a prioritised process is as simple as calling pserve -- instead of serve, and passing an initialised -- PrioritisedProcessDefinition. -- -- -- -- For advanced users and those requiring very low latency, a prioritised -- process definition might not be suitable, since it performs -- considerable work behind the scenes. There are also designs -- that need to segregate a process' control plane from other -- kinds of traffic it is expected to receive. For such use cases, a -- control channel may prove a better choice, since typed channels -- are already prioritised during the mailbox scans that the base -- receiveWait and receiveTimeout primitives from -- distribute-process provides. -- -- In order to utilise a control channel in a server, it must be -- passed to the corresponding handleControlChan function (or its -- stateless variant). The control channel is created by evaluating -- newControlChan, in the same way that we create regular typed -- channels. -- -- In order for clients to communicate with a server via its control -- channel however, they must pass a handle to a ControlPort, -- which can be obtained by evaluating channelControlPort on the -- ControlChannel. A ControlPort is Serializable, -- so they can alternatively be sent to other processes. -- -- Control channel traffic will only be prioritised over other -- traffic if the handlers using it are present before others (e.g., -- handleInfo, handleCast, etc) in the process definition. It is -- not possible to combine prioritised processes with control -- channels. Attempting to do so will satisfy the compiler, but crash -- with a runtime error once you attempt to evaluate the prioritised -- server loop (i.e., pserve). -- -- Since the primary purpose of control channels is to simplify and -- optimise client-server communication over a single channel, this -- module provides an alternate server loop in the form of -- chanServe. Instead of passing an initialised -- ProcessDefinition, this API takes an expression from a -- ControlChannel to ProcessDefinition, operating in the -- Process monad. Providing the opaque reference in this fashion -- is useful, since the type of messages the control channel carries will -- not correlate directly to the inter-process traffic we use internally. -- -- Although control channels are intended for use as a single control -- plane (via chanServe), it is possible to use them as a -- more strictly typed communications backbone, since they do enforce -- absolute type safety in client code, being bound to a particular type -- on creation. For rpc (i.e., call) interaction however, it is -- not possible to have the server reply to a control channel, since -- they're a one way pipe. It is possible to alleviate this -- situation by passing a request type than contains a typed channel -- bound to the expected reply type, enabling client and server to match -- on both the input and output types as specifically as possible. Note -- that this still does not guarantee an agreement on types between all -- parties at runtime however. -- -- An example of how to do this follows: -- --
--   data Request = Request String (SendPort String)
--     deriving (Typeable, Generic)
--   instance Binary Request where
--   
--   -- note that our initial caller needs an mvar to obtain the control port...
--   echoServer :: MVar (ControlPort Request) -> Process ()
--   echoServer mv = do
--     cc <- newControlChan :: Process (ControlChannel Request)
--     liftIO $ putMVar mv $ channelControlPort cc
--     let s = statelessProcess {
--         apiHandlers = [
--              handleControlChan_ cc (\(Request m sp) -> sendChan sp m >> continue_)
--            ]
--       }
--     serve () (statelessInit Infinity) s
--   
--   echoClient :: String -> ControlPort Request -> Process String
--   echoClient str cp = do
--     (sp, rp) <- newChan
--     sendControlMessage cp $ Request str sp
--     receiveChan rp
--   
-- -- -- -- The various server loops are fairly optimised, but there is a -- definite cost associated with scanning the mailbox to match on -- protocol messages, plus additional costs in space and time due to -- mapping over all available info handlers for non-protocol -- (i.e., neither call nor cast) messages. These are -- exacerbated significantly when using prioritisation, whilst using a -- single control channel is very fast and carries little overhead. -- -- From the client perspective, it's important to remember that the -- call protocol will wait for a reply in most cases, triggering a -- full O(n) scan of the caller's mailbox. If the mailbox is extremely -- full and calls are regularly made, this may have a significant impact -- on the caller. The callChan family of client API functions -- can alleviate this, by using (and matching on) a private typed channel -- instead, but the server must be written to accomodate this. Similar -- gains can be had using a control channel and providing a typed -- reply channel in the request data, however the call mechanism -- does not support this notion, so not only are we unable to use the -- various reply functions, client code should also consider -- monitoring the server's pid and handling server failures whilst -- waiting on module Control.Distributed.Process.ManagedProcess -- | Return type for and InitHandler expression. data InitResult s InitOk :: s -> Delay -> InitResult s InitStop :: String -> InitResult s InitIgnore :: InitResult s -- | An expression used to initialise a process with its state. type InitHandler a s = a -> Process (InitResult s) -- | Starts the message handling loop for a managed process -- configured with the supplied process definition, after calling the -- init handler with its initial arguments. Note that this function does -- not return until the server exits. serve :: a -> InitHandler a s -> ProcessDefinition s -> Process () -- | Starts the message handling loop for a prioritised managed -- process, configured with the supplied process definition, after -- calling the init handler with its initial arguments. Note that this -- function does not return until the server exits. pserve :: a -> InitHandler a s -> PrioritisedProcessDefinition s -> Process () -- | Starts the message handling loop for a managed process, -- configured with a typed control channel. The caller supplied -- expression is evaluated with an opaque reference to the channel, which -- must be passed when calling handleControlChan. The meaning -- and behaviour of the init handler and initial arguments are the same -- as those given to serve. Note that this function does not -- return until the server exits. chanServe :: Serializable b => a -> InitHandler a s -> (ControlChannel b -> Process (ProcessDefinition s)) -> Process () -- | Wraps any process loop and ensures that it adheres to the -- managed process start/stop semantics, i.e., evaluating the -- InitHandler with an initial state and delay will either -- die due to InitStop, exit silently (due to -- InitIgnore) or evaluate the process' loop. The -- supplied loop must evaluate to ExitNormal, otherwise -- the calling processing will die with whatever -- ExitReason is given. runProcess :: (s -> Delay -> Process ExitReason) -> a -> InitHandler a s -> Process () -- | Turns a standard ProcessDefinition into a -- PrioritisedProcessDefinition, by virtue of the supplied list of -- DispatchPriority expressions. prioritised :: ProcessDefinition s -> [DispatchPriority s] -> PrioritisedProcessDefinition s -- | Stores the functions that determine runtime behaviour in response to -- incoming messages and a policy for responding to unhandled messages. data ProcessDefinition s ProcessDefinition :: [Dispatcher s] -> [DeferredDispatcher s] -> [ExitSignalDispatcher s] -> TimeoutHandler s -> ShutdownHandler s -> UnhandledMessagePolicy -> ProcessDefinition s -- | functions that handle call/cast messages apiHandlers :: ProcessDefinition s -> [Dispatcher s] -- | functions that handle non call/cast messages infoHandlers :: ProcessDefinition s -> [DeferredDispatcher s] -- | functions that handle exit signals exitHandlers :: ProcessDefinition s -> [ExitSignalDispatcher s] -- | a function that handles timeouts timeoutHandler :: ProcessDefinition s -> TimeoutHandler s -- | a function that is run just before the process exits shutdownHandler :: ProcessDefinition s -> ShutdownHandler s -- | how to deal with unhandled messages unhandledMessagePolicy :: ProcessDefinition s -> UnhandledMessagePolicy -- | A ProcessDefinition decorated with DispatchPriority -- for certain input domains. data PrioritisedProcessDefinition s PrioritisedProcessDefinition :: ProcessDefinition s -> [DispatchPriority s] -> RecvTimeoutPolicy -> PrioritisedProcessDefinition s processDef :: PrioritisedProcessDefinition s -> ProcessDefinition s priorities :: PrioritisedProcessDefinition s -> [DispatchPriority s] recvTimeout :: PrioritisedProcessDefinition s -> RecvTimeoutPolicy -- | For a PrioritisedProcessDefinition, this policy determines for -- how long the receive loop should continue draining the process' -- mailbox before processing its received mail (in priority order). -- -- If a prioritised managed process is receiving a lot of messages -- (into its real mailbox), the server might never get around to -- actually processing its inputs. This (mandatory) policy provides a -- guarantee that eventually (i.e., after a specified number of received -- messages or time interval), the server will stop removing messages -- from its mailbox and process those it has already received. data RecvTimeoutPolicy RecvCounter :: Int -> RecvTimeoutPolicy RecvTimer :: TimeInterval -> RecvTimeoutPolicy newtype Priority a Priority :: Int -> Priority a getPrio :: Priority a -> Int data DispatchPriority s -- | Provides dispatch from cast and call messages to a typed handler. data Dispatcher s -- | Provides dispatch for any input, returns Nothing for unhandled -- messages. data DeferredDispatcher s -- | An expression used to handle process termination. type ShutdownHandler s = s -> ExitReason -> Process () -- | An expression used to handle process timeouts. type TimeoutHandler s = s -> Delay -> Process (ProcessAction s) -- | The action taken by a process after a handler has run and its updated -- state. See continue timeoutAfter hibernate -- stop stopWith data ProcessAction s -- | continue with (possibly new) state ProcessContinue :: s -> ProcessAction s -- | timeout if no messages are received ProcessTimeout :: Delay -> s -> ProcessAction s -- | hibernate for delay ProcessHibernate :: TimeInterval -> s -> ProcessAction s -- | stop the process, giving ExitReason ProcessStop :: ExitReason -> ProcessAction s -- | stop the process with ExitReason, with updated state ProcessStopping :: s -> ExitReason -> ProcessAction s -- | Returned from handlers for the synchronous call protocol, -- encapsulates the reply data and the action to take after -- sending the reply. A handler can return NoReply if they wish -- to ignore the call. data ProcessReply r s -- | Wraps a predicate that is used to determine whether or not a handler -- is valid based on some combination of the current process state, the -- type and/or value of the input message or both. data Condition s m -- | An expression used to handle a call message. type CallHandler s a b = s -> a -> Process (ProcessReply b s) -- | An expression used to handle a cast message. type CastHandler s a = s -> a -> Process (ProcessAction s) -- | Policy for handling unexpected messages, i.e., messages which are not -- sent using the call or cast APIs, and which are not -- handled by any of the handleInfo handlers. data UnhandledMessagePolicy -- | stop immediately, giving ExitOther UnhandledInput as -- the reason Terminate :: UnhandledMessagePolicy -- | forward the message to the given recipient DeadLetter :: ProcessId -> UnhandledMessagePolicy -- | log messages, then behave identically to Drop Log :: UnhandledMessagePolicy -- | dequeue and then drop/ignore the message Drop :: UnhandledMessagePolicy data CallRef a -- | Provides a means for servers to listen on a separate, typed -- control channel, thereby segregating the channel from their -- regular (and potentially busy) mailbox. data ControlChannel m -- | The writable end of a ControlChannel. data ControlPort m -- | A default ProcessDefinition, with no api, info or exit handler. -- The default timeoutHandler simply continues, the -- shutdownHandler is a no-op and the -- unhandledMessagePolicy is Terminate. defaultProcess :: ProcessDefinition s -- | Creates a default PrioritisedProcessDefinition from a list of -- DispatchPriority. See defaultProcess for the underlying -- definition. defaultProcessWithPriorities :: [DispatchPriority s] -> PrioritisedProcessDefinition s -- | A basic, stateless ProcessDefinition. See defaultProcess -- for the default field values. statelessProcess :: ProcessDefinition () -- | A default, state unaware InitHandler that can be used -- with statelessProcess. This simply returns InitOk with -- the empty state (i.e., unit) and the given Delay. statelessInit :: Delay -> InitHandler () () -- | Constructs a call handler from a function in the -- Process monad. > handleCall = handleCallIf (const True) handleCall :: (Serializable a, Serializable b) => (s -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Constructs a call handler from an ordinary function in the -- Process monad. Given a function f :: (s -> a -> -- Process (ProcessReply b s)), the expression handleCall f -- will yield a Dispatcher for inclusion in a Behaviour -- specification for the GenProcess. Messages are only dispatched -- to the handler if the supplied condition evaluates to True. handleCallIf :: (Serializable a, Serializable b) => Condition s a -> (s -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | As handleCall but passes the CallRef to the handler -- function. This can be useful if you wish to reply later to the -- caller by, e.g., spawning a process to do some work and have it -- replyTo caller response out of band. In this case the -- callback can pass the CallRef to the worker (or stash it away -- itself) and return noReply. handleCallFrom :: (Serializable a, Serializable b) => (s -> CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | As handleCallFrom but only runs the handler if the supplied -- Condition evaluates to True. handleCallFromIf :: (Serializable a, Serializable b) => Condition s a -> (s -> CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Constructs a cast handler from an ordinary function in the -- Process monad. > handleCast = handleCastIf (const True) handleCast :: Serializable a => (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Constructs a cast handler from an ordinary function in the -- Process monad. Given a function f :: (s -> a -> -- Process (ProcessAction s)), the expression handleCall f -- will yield a Dispatcher for inclusion in a Behaviour -- specification for the GenProcess. handleCastIf :: Serializable a => Condition s a -> (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Creates a generic input handler (i.e., for received messages that are -- not sent using the cast or call APIs) from an -- ordinary function in the Process monad. handleInfo :: Serializable a => (s -> a -> Process (ProcessAction s)) -> DeferredDispatcher s -- | Handle completely raw input messages. handleRaw :: (s -> Message -> Process (ProcessAction s)) -> DeferredDispatcher s -- | Creates a handler for a typed channel RPC style interaction. -- The handler takes a SendPort b to reply to, the initial input -- and evaluates to a ProcessAction. It is the handler code's -- responsibility to send the reply to the SendPort. handleRpcChan :: (Serializable a, Serializable b) => (s -> SendPort b -> a -> Process (ProcessAction s)) -> Dispatcher s -- | As handleRpcChan, but only evaluates the handler if the -- supplied condition is met. handleRpcChanIf :: (Serializable a, Serializable b) => Condition s a -> (s -> SendPort b -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Constructs an action handler. Like handleDispatch this -- can handle both cast and call messages, but you -- won't know which you're dealing with. This can be useful where certain -- inputs require a definite action, such as stopping the server, without -- concern for the state (e.g., when stopping we need only decide to -- stop, as the terminate handler can deal with state cleanup etc). For -- example: -- --
--   action (MyCriticalSignal -> stop_ ExitNormal)
--   
action :: Serializable a => (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Constructs a handler for both call and cast messages. -- handleDispatch = handleDispatchIf (const True) handleDispatch :: Serializable a => (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Creates an exit handler scoped to the execution of any and all -- the registered call, cast and info handlers for the process. handleExit :: Serializable a => (s -> ProcessId -> a -> Process (ProcessAction s)) -> ExitSignalDispatcher s -- | Constructs a call handler from a function in the -- Process monad. The handler expression returns the reply, and -- the action will be set to continue. -- --
--   handleCall_ = handleCallIf_ $ input (const True)
--   
handleCall_ :: (Serializable a, Serializable b) => (a -> Process b) -> Dispatcher s -- | A variant of handleCallFrom_ that ignores the state argument. handleCallFrom_ :: (Serializable a, Serializable b) => (CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Constructs a call handler from an ordinary function in the -- Process monad. This variant ignores the state argument present -- in handleCall and handleCallIf and is therefore useful -- in a stateless server. Messges are only dispatched to the handler if -- the supplied condition evaluates to True -- -- See handleCall handleCallIf_ :: (Serializable a, Serializable b) => Condition s a -> (a -> Process b) -> Dispatcher s -- | A variant of handleCallFromIf that ignores the state argument. handleCallFromIf_ :: (Serializable a, Serializable b) => (Condition s a) -> (CallRef b -> a -> Process (ProcessReply b s)) -> Dispatcher s -- | Version of handleCast that ignores the server state. handleCast_ :: Serializable a => (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Version of handleCastIf that ignores the server state. handleCastIf_ :: Serializable a => Condition s a -> (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | A variant of handleRpcChan that ignores the state argument. handleRpcChan_ :: (Serializable a, Serializable b) => (SendPort b -> a -> Process (ProcessAction ())) -> Dispatcher () -- | A variant of handleRpcChanIf that ignores the state argument. handleRpcChanIf_ :: (Serializable a, Serializable b) => Condition () a -> (SendPort b -> a -> Process (ProcessAction ())) -> Dispatcher () -- | Creates a new ControlChannel. newControlChan :: Serializable m => Process (ControlChannel m) -- | Obtain an opaque expression for communicating with a -- ControlChannel. channelControlPort :: Serializable m => ControlChannel m -> ControlPort m -- | Constructs a control channel handler from a function in the -- Process monad. The handler expression returns no reply, and the -- control message is treated in the same fashion as a -- cast. -- --
--   handleControlChan = handleControlChanIf $ input (const True)
--   
handleControlChan :: Serializable a => ControlChannel a -> (s -> a -> Process (ProcessAction s)) -> Dispatcher s -- | Version of handleControlChan that ignores the server state. handleControlChan_ :: Serializable a => ControlChannel a -> (a -> (s -> Process (ProcessAction s))) -> Dispatcher s -- | Creates a Condition from a function that takes a process state -- a and an input message b and returns a Bool -- indicating whether the associated handler should run. condition :: (Serializable a, Serializable b) => (a -> b -> Bool) -> Condition a b -- | Create a Condition from a function that takes a process state -- a and returns a Bool indicating whether the associated -- handler should run. state :: Serializable m => (s -> Bool) -> Condition s m -- | Creates a Condition from a function that takes an input message -- m and returns a Bool indicating whether the associated -- handler should run. input :: Serializable m => (m -> Bool) -> Condition s m -- | Instructs the process to send a reply and continue running. reply :: Serializable r => r -> s -> Process (ProcessReply r s) -- | Instructs the process to send a reply and evaluate the -- ProcessAction. replyWith :: Serializable r => r -> ProcessAction s -> Process (ProcessReply r s) -- | Instructs the process to skip sending a reply and evaluate a -- ProcessAction noReply :: Serializable r => ProcessAction s -> Process (ProcessReply r s) -- | Continue without giving a reply to the caller - equivalent to -- continue, but usable in a callback passed to the -- handleCall family of functions. noReply_ :: Serializable r => s -> Process (ProcessReply r s) -- | Halt process execution during a call handler, without paying any -- attention to the expected return type. haltNoReply_ :: Serializable r => ExitReason -> Process (ProcessReply r s) -- | Instructs the process to continue running and receiving messages. continue :: s -> Process (ProcessAction s) -- | Version of continue that can be used in handlers that ignore -- process state. continue_ :: s -> Process (ProcessAction s) -- | Instructs the process loop to wait for incoming messages until -- Delay is exceeded. If no messages are handled during this -- period, the timeout handler will be called. Note that this -- alters the process timeout permanently such that the given -- Delay will remain in use until changed. timeoutAfter :: Delay -> s -> Process (ProcessAction s) -- | Version of timeoutAfter that can be used in handlers that -- ignore process state. -- --
--   action (\(TimeoutPlease duration) -> timeoutAfter_ duration)
--   
timeoutAfter_ :: Delay -> (s -> Process (ProcessAction s)) -- | Instructs the process to hibernate for the given -- TimeInterval. Note that no messages will be removed from the -- mailbox until after hibernation has ceased. This is equivalent to -- calling threadDelay. hibernate :: TimeInterval -> s -> Process (ProcessAction s) -- | Version of hibernate that can be used in handlers that ignore -- process state. -- --
--   action (\(HibernatePlease delay) -> hibernate_ delay)
--   
hibernate_ :: TimeInterval -> (s -> Process (ProcessAction s)) -- | Instructs the process to terminate, giving the supplied reason. If a -- valid shutdownHandler is installed, it will be called with the -- ExitReason returned from this call, along with the process -- state. stop :: ExitReason -> Process (ProcessAction s) -- | As stop, but provides an updated state for the shutdown -- handler. stopWith :: s -> ExitReason -> Process (ProcessAction s) -- | Version of stop that can be used in handlers that ignore -- process state. -- --
--   action (\ClientError -> stop_ ExitNormal)
--   
stop_ :: ExitReason -> (s -> Process (ProcessAction s)) -- | Sends a reply explicitly to a caller. -- --
--   replyTo = sendTo
--   
replyTo :: Serializable m => CallRef m -> m -> Process () -- | Sends a reply to a SendPort (for use in handleRpcChan et -- al). -- --
--   replyChan = sendChan
--   
replyChan :: Serializable m => SendPort m -> m -> Process ()