@@ -21,6 +21,8 @@ module Control.Distributed.Process.Internal.Closure.BuiltIn
2121 , cpSend
2222 , cpExpect
2323 , cpNewChan
24+ -- * Support for some CH operations
25+ , cpDelay
2426 ) where
2527
2628import Data.ByteString.Lazy (ByteString)
@@ -49,6 +51,7 @@ import Control.Distributed.Process.Internal.Types
4951 , ProcessId
5052 , SendPort
5153 , ReceivePort
54+ , ProcessMonitorNotification(ProcessMonitorNotification)
5255 )
5356import Control.Distributed.Process.Internal.Primitives
5457 ( link
@@ -56,6 +59,11 @@ import Control.Distributed.Process.Internal.Primitives
5659 , send
5760 , expect
5861 , newChan
62+ , monitor
63+ , unmonitor
64+ , match
65+ , matchIf
66+ , receiveWait
5967 )
6068
6169--------------------------------------------------------------------------------
@@ -79,6 +87,7 @@ remoteTable =
7987 . registerStatic "$newChanDict" (toDynamic (newChanDict :: SerializableDict ANY -> Process (SendPort ANY, ReceivePort ANY)))
8088 . registerStatic "$cpSplit" (toDynamic (cpSplit :: (ANY1 -> Process ANY3) -> (ANY2 -> Process ANY4) -> (ANY1, ANY2) -> Process (ANY3, ANY4)))
8189 . registerStatic "$snd" (toDynamic (snd :: (ANY1, ANY2) -> ANY2))
90+ . registerStatic "$delay" (toDynamic delay)
8291 where
8392 decodeDict :: forall a. SerializableDict a -> ByteString -> a
8493 decodeDict SerializableDict = decode
@@ -236,3 +245,33 @@ cpNewChan dict = staticClosure (newChanDictStatic `staticApply` dict)
236245 newChanDictStatic :: Typeable a
237246 => Static (SerializableDict a -> Process (SendPort a, ReceivePort a))
238247 newChanDictStatic = staticLabel "$newChanDict"
248+
249+--------------------------------------------------------------------------------
250+-- Support for spawn --
251+--------------------------------------------------------------------------------
252+
253+-- | @delay them p@ is a process that waits for a signal (a message of type @()@)
254+-- from 'them' (origin is not verified) before proceeding as @p@. In order to
255+-- avoid waiting forever, @delay them p@ monitors 'them'. If it receives a
256+-- monitor message instead it simply terminates.
257+delay :: ProcessId -> Process () -> Process ()
258+delay them p = do
259+ ref <- monitor them
260+ let sameRef (ProcessMonitorNotification ref' _ _) = ref == ref'
261+ receiveWait [
262+ match $ \() -> unmonitor ref >> p
263+ , matchIf sameRef $ \_ -> return ()
264+ ]
265+
266+-- | 'CP' version of 'delay'
267+cpDelay :: ProcessId -> Closure (Process ()) -> Closure (Process ())
268+cpDelay = closureApply . cpDelay'
269+ where
270+ cpDelay' :: ProcessId -> Closure (Process () -> Process ())
271+ cpDelay' pid = closure decoder (encode pid)
272+
273+ decoder :: Static (ByteString -> Process () -> Process ())
274+ decoder = delayStatic `staticCompose` decodeProcessIdStatic
275+
276+ delayStatic :: Static (ProcessId -> Process () -> Process ())
277+ delayStatic = staticLabel "$delay"