module Control.Distributed.Process.ManagedProcess.Server
(
condition
, state
, input
, reply
, replyWith
, noReply
, continue
, timeoutAfter
, hibernate
, stop
, stopWith
, replyTo
, replyChan
, noReply_
, haltNoReply_
, continue_
, timeoutAfter_
, hibernate_
, stop_
, handleCall
, handleCallIf
, handleCallFrom
, handleCallFromIf
, handleRpcChan
, handleRpcChanIf
, handleCast
, handleCastIf
, handleInfo
, handleRaw
, handleDispatch
, handleDispatchIf
, handleExit
, handleExitIf
, action
, handleCall_
, handleCallIf_
, handleCallFrom_
, handleCallFromIf_
, handleRpcChan_
, handleRpcChanIf_
, handleCast_
, handleCastIf_
, handleControlChan
, handleControlChan_
) where
import Control.Distributed.Process hiding (call, Message)
import qualified Control.Distributed.Process as P (Message)
import Control.Distributed.Process.Serializable
import Control.Distributed.Process.ManagedProcess.Internal.Types
import Control.Distributed.Process.Extras
( ExitReason(..)
, Routable(..)
)
import Control.Distributed.Process.Extras.Time
import Prelude hiding (init)
condition :: forall a b. (Serializable a, Serializable b)
=> (a -> b -> Bool)
-> Condition a b
condition = Condition
state :: forall s m. (Serializable m) => (s -> Bool) -> Condition s m
state = State
input :: forall s m. (Serializable m) => (m -> Bool) -> Condition s m
input = Input
reply :: (Serializable r) => r -> s -> Process (ProcessReply r s)
reply r s = continue s >>= replyWith r
replyWith :: (Serializable r)
=> r
-> ProcessAction s
-> Process (ProcessReply r s)
replyWith r s = return $ ProcessReply r s
noReply :: (Serializable r) => ProcessAction s -> Process (ProcessReply r s)
noReply = return . NoReply
noReply_ :: forall s r . (Serializable r) => s -> Process (ProcessReply r s)
noReply_ s = continue s >>= noReply
haltNoReply_ :: Serializable r => ExitReason -> Process (ProcessReply r s)
haltNoReply_ r = stop r >>= noReply
continue :: s -> Process (ProcessAction s)
continue = return . ProcessContinue
continue_ :: (s -> Process (ProcessAction s))
continue_ = return . ProcessContinue
timeoutAfter :: Delay -> s -> Process (ProcessAction s)
timeoutAfter d s = return $ ProcessTimeout d s
timeoutAfter_ :: Delay -> (s -> Process (ProcessAction s))
timeoutAfter_ d = return . ProcessTimeout d
hibernate :: TimeInterval -> s -> Process (ProcessAction s)
hibernate d s = return $ ProcessHibernate d s
hibernate_ :: TimeInterval -> (s -> Process (ProcessAction s))
hibernate_ d = return . ProcessHibernate d
stop :: ExitReason -> Process (ProcessAction s)
stop r = return $ ProcessStop r
stopWith :: s -> ExitReason -> Process (ProcessAction s)
stopWith s r = return $ ProcessStopping s r
stop_ :: ExitReason -> (s -> Process (ProcessAction s))
stop_ r _ = stop r
replyTo :: (Serializable m) => CallRef m -> m -> Process ()
replyTo = sendTo
replyChan :: (Serializable m) => SendPort m -> m -> Process ()
replyChan = sendChan
handleCall_ :: (Serializable a, Serializable b)
=> (a -> Process b)
-> Dispatcher s
handleCall_ = handleCallIf_ $ input (const True)
handleCallIf_ :: forall s a b . (Serializable a, Serializable b)
=> Condition s a
-> (a -> Process b)
-> Dispatcher s
handleCallIf_ cond handler
= DispatchIf {
dispatch = doHandle handler
, dispatchIf = checkCall cond
}
where doHandle :: (Serializable a, Serializable b)
=> (a -> Process b)
-> s
-> Message a b
-> Process (ProcessAction s)
doHandle h s (CallMessage p c) = (h p) >>= mkCallReply c s
doHandle _ _ _ = die "CALL_HANDLER_TYPE_MISMATCH"
mkCallReply :: (Serializable b)
=> CallRef b
-> s
-> b
-> Process (ProcessAction s)
mkCallReply c s m =
let (c', t) = unCaller c
in sendTo c' (CallResponse m t) >> continue s
handleCall :: (Serializable a, Serializable b)
=> (s -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCall = handleCallIf $ state (const True)
handleCallIf :: forall s a b . (Serializable a, Serializable b)
=> Condition s a
-> (s -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCallIf cond handler
= DispatchIf {
dispatch = doHandle handler
, dispatchIf = checkCall cond
}
where doHandle :: (Serializable a, Serializable b)
=> (s -> a -> Process (ProcessReply b s))
-> s
-> Message a b
-> Process (ProcessAction s)
doHandle h s (CallMessage p c) = (h s p) >>= mkReply c
doHandle _ _ _ = die "CALL_HANDLER_TYPE_MISMATCH"
handleCallFrom_ :: forall s a b . (Serializable a, Serializable b)
=> (CallRef b -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCallFrom_ = handleCallFromIf_ $ input (const True)
handleCallFromIf_ :: forall s a b . (Serializable a, Serializable b)
=> (Condition s a)
-> (CallRef b -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCallFromIf_ c h =
DispatchIf {
dispatch = doHandle h
, dispatchIf = checkCall c
}
where doHandle :: (Serializable a, Serializable b)
=> (CallRef b -> a -> Process (ProcessReply b s))
-> s
-> Message a b
-> Process (ProcessAction s)
doHandle h' _ (CallMessage p c') = (h' c' p) >>= mkReply c'
doHandle _ _ _ = die "CALL_HANDLER_TYPE_MISMATCH"
handleCallFrom :: forall s a b . (Serializable a, Serializable b)
=> (s -> CallRef b -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCallFrom = handleCallFromIf $ state (const True)
handleCallFromIf :: forall s a b . (Serializable a, Serializable b)
=> Condition s a
-> (s -> CallRef b -> a -> Process (ProcessReply b s))
-> Dispatcher s
handleCallFromIf cond handler
= DispatchIf {
dispatch = doHandle handler
, dispatchIf = checkCall cond
}
where doHandle :: (Serializable a, Serializable b)
=> (s -> CallRef b -> a -> Process (ProcessReply b s))
-> s
-> Message a b
-> Process (ProcessAction s)
doHandle h s (CallMessage p c) = (h s c p) >>= mkReply c
doHandle _ _ _ = die "CALL_HANDLER_TYPE_MISMATCH"
handleRpcChan :: forall s a b . (Serializable a, Serializable b)
=> (s -> SendPort b -> a -> Process (ProcessAction s))
-> Dispatcher s
handleRpcChan = handleRpcChanIf $ input (const True)
handleRpcChanIf :: forall s a b . (Serializable a, Serializable b)
=> Condition s a
-> (s -> SendPort b -> a -> Process (ProcessAction s))
-> Dispatcher s
handleRpcChanIf c h
= DispatchIf {
dispatch = doHandle h
, dispatchIf = checkRpc c
}
where doHandle :: (Serializable a, Serializable b)
=> (s -> SendPort b -> a -> Process (ProcessAction s))
-> s
-> Message a b
-> Process (ProcessAction s)
doHandle h' s (ChanMessage p c') = h' s c' p
doHandle _ _ _ = die "RPC_HANDLER_TYPE_MISMATCH"
handleRpcChan_ :: forall a b . (Serializable a, Serializable b)
=> (SendPort b -> a -> Process (ProcessAction ()))
-> Dispatcher ()
handleRpcChan_ h = handleRpcChan (\() -> h)
handleRpcChanIf_ :: forall a b . (Serializable a, Serializable b)
=> Condition () a
-> (SendPort b -> a -> Process (ProcessAction ()))
-> Dispatcher ()
handleRpcChanIf_ c h = handleRpcChanIf c (\() -> h)
handleCast :: (Serializable a)
=> (s -> a -> Process (ProcessAction s))
-> Dispatcher s
handleCast = handleCastIf $ input (const True)
handleCastIf :: forall s a . (Serializable a)
=> Condition s a
-> (s -> a -> Process (ProcessAction s))
-> Dispatcher s
handleCastIf cond h
= DispatchIf {
dispatch = (\s ((CastMessage p) :: Message a ()) -> h s p)
, dispatchIf = checkCast cond
}
handleControlChan :: forall s a . (Serializable a)
=> ControlChannel a
-> (s -> a -> Process (ProcessAction s))
-> Dispatcher s
handleControlChan chan h
= DispatchCC { channel = snd $ unControl chan
, dispatch = (\s ((CastMessage p) :: Message a ()) -> h s p)
}
handleControlChan_ :: forall s a. (Serializable a)
=> ControlChannel a
-> (a -> (s -> Process (ProcessAction s)))
-> Dispatcher s
handleControlChan_ chan h
= DispatchCC { channel = snd $ unControl chan
, dispatch = (\s ((CastMessage p) :: Message a ()) -> h p $ s)
}
handleCast_ :: (Serializable a)
=> (a -> (s -> Process (ProcessAction s))) -> Dispatcher s
handleCast_ = handleCastIf_ $ input (const True)
handleCastIf_ :: forall s a . (Serializable a)
=> Condition s a
-> (a -> (s -> Process (ProcessAction s)))
-> Dispatcher s
handleCastIf_ cond h
= DispatchIf { dispatch = (\s ((CastMessage p) :: Message a ()) -> h p $ s)
, dispatchIf = checkCast cond
}
action :: forall s a . (Serializable a)
=> (a -> (s -> Process (ProcessAction s)))
-> Dispatcher s
action h = handleDispatch perform
where perform :: (s -> a -> Process (ProcessAction s))
perform s a = let f = h a in f s
handleDispatch :: forall s a . (Serializable a)
=> (s -> a -> Process (ProcessAction s))
-> Dispatcher s
handleDispatch = handleDispatchIf $ input (const True)
handleDispatchIf :: forall s a . (Serializable a)
=> Condition s a
-> (s -> a -> Process (ProcessAction s))
-> Dispatcher s
handleDispatchIf cond handler = DispatchIf {
dispatch = doHandle handler
, dispatchIf = check cond
}
where doHandle :: (Serializable a)
=> (s -> a -> Process (ProcessAction s))
-> s
-> Message a ()
-> Process (ProcessAction s)
doHandle h s msg =
case msg of
(CallMessage p _) -> (h s p)
(CastMessage p) -> (h s p)
(ChanMessage p _) -> (h s p)
handleInfo :: forall s a. (Serializable a)
=> (s -> a -> Process (ProcessAction s))
-> DeferredDispatcher s
handleInfo h = DeferredDispatcher { dispatchInfo = doHandleInfo h }
where
doHandleInfo :: forall s2 a2. (Serializable a2)
=> (s2 -> a2 -> Process (ProcessAction s2))
-> s2
-> P.Message
-> Process (Maybe (ProcessAction s2))
doHandleInfo h' s msg = handleMessage msg (h' s)
handleRaw :: forall s. (s -> P.Message -> Process (ProcessAction s))
-> DeferredDispatcher s
handleRaw h = DeferredDispatcher { dispatchInfo = doHandle h }
where
doHandle h' s msg = h' s msg >>= return . Just
handleExit :: forall s a. (Serializable a)
=> (s -> ProcessId -> a -> Process (ProcessAction s))
-> ExitSignalDispatcher s
handleExit h = ExitSignalDispatcher { dispatchExit = doHandleExit h }
where
doHandleExit :: (s -> ProcessId -> a -> Process (ProcessAction s))
-> s
-> ProcessId
-> P.Message
-> Process (Maybe (ProcessAction s))
doHandleExit h' s p msg = handleMessage msg (h' s p)
handleExitIf :: forall s a . (Serializable a)
=> (s -> a -> Bool)
-> (s -> ProcessId -> a -> Process (ProcessAction s))
-> ExitSignalDispatcher s
handleExitIf c h = ExitSignalDispatcher { dispatchExit = doHandleExit c h }
where
doHandleExit :: (s -> a -> Bool)
-> (s -> ProcessId -> a -> Process (ProcessAction s))
-> s
-> ProcessId
-> P.Message
-> Process (Maybe (ProcessAction s))
doHandleExit c' h' s p msg = handleMessageIf msg (c' s) (h' s p)
mkReply :: (Serializable b)
=> CallRef b
-> ProcessReply b s
-> Process (ProcessAction s)
mkReply _ (NoReply a) = return a
mkReply c (ProcessReply r' a) = sendTo c r' >> return a
check :: forall s m a . (Serializable m)
=> Condition s m
-> s
-> Message m a
-> Bool
check (Condition c) st msg = c st $ decode msg
check (State c) st _ = c st
check (Input c) _ msg = c $ decode msg
checkRpc :: forall s m a . (Serializable m)
=> Condition s m
-> s
-> Message m a
-> Bool
checkRpc cond st msg@(ChanMessage _ _) = check cond st msg
checkRpc _ _ _ = False
checkCall :: forall s m a . (Serializable m)
=> Condition s m
-> s
-> Message m a
-> Bool
checkCall cond st msg@(CallMessage _ _) = check cond st msg
checkCall _ _ _ = False
checkCast :: forall s m . (Serializable m)
=> Condition s m
-> s
-> Message m ()
-> Bool
checkCast cond st msg@(CastMessage _) = check cond st msg
checkCast _ _ _ = False
decode :: Message a b -> a
decode (CallMessage a _) = a
decode (CastMessage a) = a
decode (ChanMessage a _) = a