git.iko.soy/distributed-process
on master help sign in
Start putting infrastructure in place for spawn
3850c69Edsko de Vries
distributed-process/src/Control/Distributed/Process.hs+31−12
@@ -43,6 +43,7 @@ module Control.Distributed.Process
43 , closeLocalNode
43 , closeLocalNode
44 , catch
44 , catch
45 , expectTimeout
45 , expectTimeout
46+ , spawnAsync
46 ) where
47 ) where
47
48
48import Prelude hiding (catch)
49import Prelude hiding (catch)
@@ -56,7 +57,6 @@ import qualified Data.List as List (delete)
56import Data.Set (Set)
57import Data.Set (Set)
57import qualified Data.Set as Set (empty, insert, delete, member)
58import qualified Data.Set as Set (empty, insert, delete, member)
58import Data.Foldable (forM_)
59import Data.Foldable (forM_)
59−import Data.Typeable (Typeable)
60import Control.Monad (void)
60import Control.Monad (void)
61import Control.Monad.Reader (MonadReader(..), ReaderT, runReaderT)
61import Control.Monad.Reader (MonadReader(..), ReaderT, runReaderT)
62import Control.Monad.IO.Class (MonadIO, liftIO)
62import Control.Monad.IO.Class (MonadIO, liftIO)
@@ -104,6 +104,8 @@ import Control.Distributed.Process.Internal ( RemoteTable
104 , LocalNodeState(..)
104 , LocalNodeState(..)
105 , LocalProcess(..)
105 , LocalProcess(..)
106 , LocalProcessState(..)
106 , LocalProcessState(..)
107+ , Process(..)
108+ , Closure
107 , Message(..)
109 , Message(..)
108 , MonitorRef(..)
110 , MonitorRef(..)
109 , MonitorNotification(..)
111 , MonitorNotification(..)
@@ -111,6 +113,7 @@ import Control.Distributed.Process.Internal ( RemoteTable
111 , DidUnmonitor(..)
113 , DidUnmonitor(..)
112 , DidUnlink(..)
114 , DidUnlink(..)
113 , DiedReason(..)
115 , DiedReason(..)
116+ , SpawnRef(..)
114 , NCMsg(..)
117 , NCMsg(..)
115 , ProcessSignal(..)
118 , ProcessSignal(..)
116 , createMessage
119 , createMessage
@@ -121,7 +124,8 @@ import Control.Distributed.Process.Internal ( RemoteTable
121 , localPidCounter
124 , localPidCounter
122 , localPidUnique
125 , localPidUnique
123 , localProcessWithId
126 , localProcessWithId
124− , localMonitorCounter
127+ , monitorCounter
128+ , spawnCounter
125 , connectionTo
129 , connectionTo
126 )
130 )
127
131
@@ -188,10 +192,6 @@ import Control.Distributed.Process.Internal ( RemoteTable
188-- Basic Cloud Haskell API --
192-- Basic Cloud Haskell API --
189--------------------------------------------------------------------------------
193--------------------------------------------------------------------------------
190
194
191−-- | The Cloud Haskell 'Process' type
192−newtype Process a = Process { unProcess :: ReaderT LocalProcess IO a }
193− deriving (Functor, Monad, MonadIO, MonadReader LocalProcess, Typeable)
194−
195-- | Wait for a message of a specific type
195-- | Wait for a message of a specific type
196expect :: forall a. Serializable a => Process a
196expect :: forall a. Serializable a => Process a
197expect = receiveWait [match return]
197expect = receiveWait [match return]
@@ -288,6 +288,15 @@ catch p h = do
288expectTimeout :: forall a. Serializable a => Int -> Process (Maybe a)
288expectTimeout :: forall a. Serializable a => Int -> Process (Maybe a)
289expectTimeout timeout = receiveTimeout timeout [match return]
289expectTimeout timeout = receiveTimeout timeout [match return]
290
290
291+-- | Asynchronous version of 'spawn'
292+--
293+-- ('spawn' is defined in terms of 'spawnAsync' and 'expect')
294+spawnAsync :: NodeId -> Closure (Process ()) -> Process SpawnRef
295+spawnAsync _nid proc = do
296+ spawnRef <- getSpawnRef
297+ postCtrlMsg (Spawn proc spawnRef)
298+ return spawnRef
299+
291--------------------------------------------------------------------------------
300--------------------------------------------------------------------------------
292-- Initialization --
301-- Initialization --
293--------------------------------------------------------------------------------
302--------------------------------------------------------------------------------
@@ -307,7 +316,6 @@ newLocalNode transport rtable = do
307 { _localProcesses = Map.empty
316 { _localProcesses = Map.empty
308 , _localPidCounter = 0
317 , _localPidCounter = 0
309 , _localPidUnique = unq
318 , _localPidUnique = unq
310− , _localMonitorCounter = 0
311 }
319 }
312 ctrlChan <- newChan
320 ctrlChan <- newChan
313 let node = LocalNode { localNodeId = NodeId $ NT.address endPoint
321 let node = LocalNode { localNodeId = NodeId $ NT.address endPoint
@@ -336,7 +344,9 @@ forkProcess node proc = modifyMVar (localState node) $ \st -> do
336 let pid = ProcessId { processNodeId = localNodeId node
344 let pid = ProcessId { processNodeId = localNodeId node
337 , processLocalId = lpid
345 , processLocalId = lpid
338 }
346 }
339− pst <- newMVar LocalProcessState { _connections = Map.empty
347+ pst <- newMVar LocalProcessState { _connections = Map.empty
348+ , _monitorCounter = 0
349+ , _spawnCounter = 0
340 }
350 }
341 queue <- newCQueue
351 queue <- newCQueue
342 (_, lproc) <- fixIO $ \ ~(tid, _) -> do
352 (_, lproc) <- fixIO $ \ ~(tid, _) -> do
@@ -493,13 +503,22 @@ remoteProcessFailed node them = do
493
503
494getMonitorRefFor :: ProcessId -> Process MonitorRef
504getMonitorRefFor :: ProcessId -> Process MonitorRef
495getMonitorRefFor pid = do
505getMonitorRefFor pid = do
496− node <- processNode <$> ask
506+ proc <- ask
497− liftIO $ modifyMVar (localState node) $ \st -> do
507+ liftIO $ modifyMVar (processState proc) $ \st -> do
498− let counter = st ^. localMonitorCounter
508+ let counter = st ^. monitorCounter
499− return ( localMonitorCounter ^: (+ 1) $ st
509+ return ( monitorCounter ^: (+ 1) $ st
500 , MonitorRef pid counter
510 , MonitorRef pid counter
501 )
511 )
502
512
513+getSpawnRef :: Process SpawnRef
514+getSpawnRef = do
515+ proc <- ask
516+ liftIO $ modifyMVar (processState proc) $ \st -> do
517+ let counter = st ^. spawnCounter
518+ return ( spawnCounter ^: (+ 1) $ st
519+ , SpawnRef counter
520+ )
521+
503-- This is most definitely NOT exported
522-- This is most definitely NOT exported
504runLocalProcess :: LocalProcess -> Process a -> IO a
523runLocalProcess :: LocalProcess -> Process a -> IO a
505runLocalProcess lproc proc = runReaderT (unProcess proc) lproc
524runLocalProcess lproc proc = runReaderT (unProcess proc) lproc
distributed-process/src/Control/Distributed/Process/Closure.hs+4−15
@@ -47,11 +47,11 @@ module Control.Distributed.Process.Closure
47
47
48import Prelude hiding (lookup)
48import Prelude hiding (lookup)
49import Data.ByteString.Lazy (ByteString)
49import Data.ByteString.Lazy (ByteString)
50−import Data.Binary (Binary(..), encode, decode)
50+import Data.Binary (encode, decode)
51import qualified Data.Map as Map (insert, (!))
51import qualified Data.Map as Map (insert, (!))
52import Data.Dynamic (toDyn, fromDyn)
52import Data.Dynamic (toDyn, fromDyn)
53import Data.Typeable (Typeable)
53import Data.Typeable (Typeable)
54−import Control.Applicative ((<$>), (<*>))
54+import Control.Applicative ((<$>))
55import Control.Monad.Reader (ask)
55import Control.Monad.Reader (ask)
56import Control.Exception (throw)
56import Control.Exception (throw)
57import Language.Haskell.TH ( -- Q monad and operations
57import Language.Haskell.TH ( -- Q monad and operations
@@ -83,17 +83,10 @@ import Control.Distributed.Process (Process)
83import Control.Distributed.Process.Internal ( RemoteTable
83import Control.Distributed.Process.Internal ( RemoteTable
84 , LocalProcess(processNode)
84 , LocalProcess(processNode)
85 , LocalNode(remoteTable)
85 , LocalNode(remoteTable)
86+ , Closure(..)
87+ , Static(..)
86 )
88 )
87
89
88−-- | A static value is one that is bound at top-level.
89−-- We represent it simply by a string
90−newtype Static a = Static String
91− deriving (Typeable)
92−
93−-- | A closure is a static value and an encoded environment
94−data Closure a = Closure (Static (ByteString -> a)) ByteString
95− deriving (Typeable)
96−
97--------------------------------------------------------------------------------
90--------------------------------------------------------------------------------
98-- Top-level API --
91-- Top-level API --
99--------------------------------------------------------------------------------
92--------------------------------------------------------------------------------
@@ -127,10 +120,6 @@ lookupStatic label = do
127 where
120 where
128 typeError = userError "lookupStatic type error"
121 typeError = userError "lookupStatic type error"
129
122
130−instance Binary (Closure a) where
131− put (Closure (Static label) env) = put label >> put env
132− get = Closure <$> (Static <$> get) <*> get
133−
134--------------------------------------------------------------------------------
123--------------------------------------------------------------------------------
135-- Internal (Template Haskell) --
124-- Internal (Template Haskell) --
136--------------------------------------------------------------------------------
125--------------------------------------------------------------------------------
distributed-process/src/Control/Distributed/Process/Internal.hs+97−24
@@ -6,22 +6,27 @@ module Control.Distributed.Process.Internal
6 NodeId(..)
6 NodeId(..)
7 , LocalProcessId(..)
7 , LocalProcessId(..)
8 , ProcessId(..)
8 , ProcessId(..)
9+ , Identifier
9 -- * Local nodes and processes
10 -- * Local nodes and processes
10 , LocalNode(..)
11 , LocalNode(..)
11 , LocalNodeState(..)
12 , LocalNodeState(..)
12 , LocalProcess(..)
13 , LocalProcess(..)
13 , LocalProcessState(..)
14 , LocalProcessState(..)
15+ , Process(..)
16+ -- * Closures
17+ , Static(..)
18+ , Closure(..)
14 -- * Messages
19 -- * Messages
15 , Message(..)
20 , Message(..)
16− -- * Monitoring and linking
21+ -- * Node controller user-visible data types
17 , MonitorRef(..)
22 , MonitorRef(..)
18 , MonitorNotification(..)
23 , MonitorNotification(..)
19 , LinkException(..)
24 , LinkException(..)
20 , DiedReason(..)
25 , DiedReason(..)
21 , DidUnmonitor(..)
26 , DidUnmonitor(..)
22 , DidUnlink(..)
27 , DidUnlink(..)
28+ , SpawnRef(..)
23− -- * Node controller data types
29+ -- * Node controller internal data types
24− , Identifier
25 , NCMsg(..)
30 , NCMsg(..)
26 , ProcessSignal(..)
31 , ProcessSignal(..)
27 -- * Serialization/deserialization
32 -- * Serialization/deserialization
@@ -34,9 +39,10 @@ module Control.Distributed.Process.Internal
34 , localProcesses
39 , localProcesses
35 , localPidCounter
40 , localPidCounter
36 , localPidUnique
41 , localPidUnique
37− , localMonitorCounter
38 , localProcessWithId
42 , localProcessWithId
39 , connections
43 , connections
44+ , monitorCounter
45+ , spawnCounter
40 , connectionTo
46 , connectionTo
41 ) where
47 ) where
42
48
@@ -51,6 +57,7 @@ import Data.Int (Int32)
51import Data.Typeable (Typeable)
57import Data.Typeable (Typeable)
52import Data.Dynamic (Dynamic)
58import Data.Dynamic (Dynamic)
53import Data.Binary (Binary, encode, put, get, putWord8, getWord8)
59import Data.Binary (Binary, encode, put, get, putWord8, getWord8)
60+import Data.ByteString.Lazy (ByteString)
54import Data.Accessor (Accessor, accessor)
61import Data.Accessor (Accessor, accessor)
55import qualified Data.Accessor.Container as DAC (mapMaybe)
62import qualified Data.Accessor.Container as DAC (mapMaybe)
56import qualified Data.ByteString.Lazy as BSL (ByteString, toChunks, fromChunks, splitAt)
63import qualified Data.ByteString.Lazy as BSL (ByteString, toChunks, fromChunks, splitAt)
@@ -58,6 +65,8 @@ import qualified Data.ByteString as BSS (ByteString, concat, splitAt)
58import qualified Network.Transport as NT (EndPoint, EndPointAddress, Connection)
65import qualified Network.Transport as NT (EndPoint, EndPointAddress, Connection)
59import qualified Network.Transport.Internal as NTI (encodeInt32, decodeInt32)
66import qualified Network.Transport.Internal as NTI (encodeInt32, decodeInt32)
60import Control.Applicative ((<$>), (<*>))
67import Control.Applicative ((<$>), (<*>))
68+import Control.Monad.Reader (MonadReader(..), ReaderT)
69+import Control.Monad.IO.Class (MonadIO)
61import Control.Distributed.Process.Serializable ( Fingerprint
70import Control.Distributed.Process.Serializable ( Fingerprint
62 , Serializable
71 , Serializable
63 , encodeFingerprint
72 , encodeFingerprint
@@ -67,6 +76,21 @@ import Control.Distributed.Process.Serializable ( Fingerprint
67 )
76 )
68import Control.Distributed.Process.Internal.CQueue (CQueue)
77import Control.Distributed.Process.Internal.CQueue (CQueue)
69
78
79+--------------------------------------------------------------------------------
80+-- Global state --
81+--------------------------------------------------------------------------------
82+
83+-- | Used to fake 'static' (see paper)
84+type RemoteTable = Map String Dynamic
85+
86+-- | Initial (empty) remote-call meta data
87+initRemoteTable :: RemoteTable
88+initRemoteTable = Map.empty
89+
90+--------------------------------------------------------------------------------
91+-- Node and process identifiers --
92+--------------------------------------------------------------------------------
93+
70-- | Node identifier
94-- | Node identifier
71newtype NodeId = NodeId { nodeAddress :: NT.EndPointAddress }
95newtype NodeId = NodeId { nodeAddress :: NT.EndPointAddress }
72 deriving (Eq, Ord, Binary)
96 deriving (Eq, Ord, Binary)
@@ -95,12 +119,12 @@ data ProcessId = ProcessId
95instance Show ProcessId where
119instance Show ProcessId where
96 show pid = show (processNodeId pid) ++ ":" ++ show (processLocalId pid)
120 show pid = show (processNodeId pid) ++ ":" ++ show (processLocalId pid)
97
121
98−-- | Used to fake 'static' (see paper)
122+-- | Node or process identifier
99−type RemoteTable = Map String Dynamic
123+type Identifier = Either ProcessId NodeId
100
124
101−-- | Initial (empty) remote-call meta data
125+--------------------------------------------------------------------------------
102−initRemoteTable :: RemoteTable
126+-- Local nodes and processes --
103−initRemoteTable = Map.empty
127+--------------------------------------------------------------------------------
104
128
105-- | Local nodes
129-- | Local nodes
106data LocalNode = LocalNode
130data LocalNode = LocalNode
@@ -117,7 +141,6 @@ data LocalNodeState = LocalNodeState
117 { _localProcesses :: Map LocalProcessId LocalProcess
141 { _localProcesses :: Map LocalProcessId LocalProcess
118 , _localPidCounter :: Int32
142 , _localPidCounter :: Int32
119 , _localPidUnique :: Int32
143 , _localPidUnique :: Int32
120− , _localMonitorCounter :: Int32
121 }
144 }
122
145
123-- | Processes running on our local node
146-- | Processes running on our local node
@@ -132,17 +155,46 @@ data LocalProcess = LocalProcess
132-- | Local process state
155-- | Local process state
133data LocalProcessState = LocalProcessState
156data LocalProcessState = LocalProcessState
134 { _connections :: Map ProcessId NT.Connection
157 { _connections :: Map ProcessId NT.Connection
158+ , _monitorCounter :: Int32
159+ , _spawnCounter :: Int32
135 }
160 }
136
161
162+-- | The Cloud Haskell 'Process' type
163+newtype Process a = Process { unProcess :: ReaderT LocalProcess IO a }
164+ deriving (Functor, Monad, MonadIO, MonadReader LocalProcess, Typeable)
165+
166+--------------------------------------------------------------------------------
167+-- Closures --
168+--------------------------------------------------------------------------------
169+
170+-- | A static value is one that is bound at top-level.
171+-- We represent it simply by a string
172+newtype Static a = Static String
173+ deriving (Typeable, Show)
174+
175+-- | A closure is a static value and an encoded environment
176+data Closure a = Closure (Static (ByteString -> a)) ByteString
177+ deriving (Typeable, Show)
178+
179+--------------------------------------------------------------------------------
180+-- Messages --
181+--------------------------------------------------------------------------------
182+
137-- | Messages consist of their typeRep fingerprint and their encoding
183-- | Messages consist of their typeRep fingerprint and their encoding
138data Message = Message
184data Message = Message
139 { messageFingerprint :: Fingerprint
185 { messageFingerprint :: Fingerprint
140 , messageEncoding :: BSL.ByteString
186 , messageEncoding :: BSL.ByteString
141 }
187 }
142
188
189+--------------------------------------------------------------------------------
190+-- Node controller user-visible data types --
191+--------------------------------------------------------------------------------
192+
143-- | MonitorRef is opaque for regular Cloud Haskell processes
193-- | MonitorRef is opaque for regular Cloud Haskell processes
144data MonitorRef = MonitorRef
194data MonitorRef = MonitorRef
195+ { -- | PID of the process to be monitored (for routing purposes)
145− { monitorRefPid :: ProcessId
196+ monitorRefPid :: ProcessId
197+ -- | Unique to distinguish multiple monitor requests by the same process
146 , monitorRefCounter :: Int32
198 , monitorRefCounter :: Int32
147 }
199 }
148 deriving (Eq, Ord, Show)
200 deriving (Eq, Ord, Show)
@@ -157,14 +209,6 @@ data LinkException = LinkException ProcessId DiedReason
157
209
158instance Exception LinkException
210instance Exception LinkException
159
211
160−-- | (Asynchronous) reply from unmonitor
161−newtype DidUnmonitor = DidUnmonitor MonitorRef
162− deriving (Typeable, Binary)
163−
164−-- | (Asynchronous) reply from unlink
165−newtype DidUnlink = DidUnlink ProcessId
166− deriving (Typeable, Binary)
167−
168-- | Why did a process die?
212-- | Why did a process die?
169data DiedReason =
213data DiedReason =
170 -- | Normal termination
214 -- | Normal termination
@@ -180,8 +224,21 @@ data DiedReason =
180 | DiedNoProc
224 | DiedNoProc
181 deriving (Show, Eq)
225 deriving (Show, Eq)
182
226
183−-- | Node or process identifier
227+-- | (Asynchronous) reply from unmonitor
184−type Identifier = Either ProcessId NodeId
228+newtype DidUnmonitor = DidUnmonitor MonitorRef
229+ deriving (Typeable, Binary)
230+
231+-- | (Asynchronous) reply from unlink
232+newtype DidUnlink = DidUnlink ProcessId
233+ deriving (Typeable, Binary)
234+
235+-- | 'SpawnRef' are used to return pids of spawned processes
236+newtype SpawnRef = SpawnRef Int32
237+ deriving (Show, Binary, Typeable)
238+
239+--------------------------------------------------------------------------------
240+-- Node controller internal data types --
241+--------------------------------------------------------------------------------
185
242
186-- | Messages to the node controller
243-- | Messages to the node controller
187data NCMsg = NCMsg
244data NCMsg = NCMsg
@@ -197,6 +254,7 @@ data ProcessSignal =
197 | Monitor ProcessId MonitorRef
254 | Monitor ProcessId MonitorRef
198 | Unmonitor MonitorRef
255 | Unmonitor MonitorRef
199 | Died Identifier DiedReason
256 | Died Identifier DiedReason
257+ | Spawn (Closure (Process ())) SpawnRef
200 deriving Show
258 deriving Show
201
259
202--------------------------------------------------------------------------------
260--------------------------------------------------------------------------------
@@ -241,6 +299,10 @@ payloadToId bss = let (bs1, bss') = BSS.splitAt 4 . BSS.concat $ bss
241 }
299 }
242 _ -> fail "payloadToId"
300 _ -> fail "payloadToId"
243
301
302+--------------------------------------------------------------------------------
303+-- Binary instances --
304+--------------------------------------------------------------------------------
305+
244instance Binary LocalProcessId where
306instance Binary LocalProcessId where
245 put lpid = put (lpidUnique lpid) >> put (lpidCounter lpid)
307 put lpid = put (lpidUnique lpid) >> put (lpidCounter lpid)
246 get = LocalProcessId <$> get <*> get
308 get = LocalProcessId <$> get <*> get
@@ -267,6 +329,7 @@ instance Binary ProcessSignal where
267 put (Monitor pid ref) = putWord8 2 >> put pid >> put ref
329 put (Monitor pid ref) = putWord8 2 >> put pid >> put ref
268 put (Unmonitor ref) = putWord8 3 >> put ref
330 put (Unmonitor ref) = putWord8 3 >> put ref
269 put (Died who reason) = putWord8 4 >> put who >> put reason
331 put (Died who reason) = putWord8 4 >> put who >> put reason
332+ put (Spawn proc ref) = putWord8 5 >> put proc >> put ref
270 get = do
333 get = do
271 header <- getWord8
334 header <- getWord8
272 case header of
335 case header of
@@ -275,6 +338,7 @@ instance Binary ProcessSignal where
275 2 -> Monitor <$> get <*> get
338 2 -> Monitor <$> get <*> get
276 3 -> Unmonitor <$> get
339 3 -> Unmonitor <$> get
277 4 -> Died <$> get <*> get
340 4 -> Died <$> get <*> get
341+ 5 -> Spawn <$> get <*> get
278 _ -> fail "ProcessSignal.get: invalid"
342 _ -> fail "ProcessSignal.get: invalid"
279
343
280instance Binary DiedReason where
344instance Binary DiedReason where
@@ -293,6 +357,10 @@ instance Binary DiedReason where
293 4 -> return DiedNoProc
357 4 -> return DiedNoProc
294 _ -> fail "DiedReason.get: invalid"
358 _ -> fail "DiedReason.get: invalid"
295
359
360+instance Binary (Closure a) where
361+ put (Closure (Static label) env) = put label >> put env
362+ get = Closure <$> (Static <$> get) <*> get
363+
296--------------------------------------------------------------------------------
364--------------------------------------------------------------------------------
297-- Accessors --
365-- Accessors --
298--------------------------------------------------------------------------------
366--------------------------------------------------------------------------------
@@ -306,14 +374,19 @@ localPidCounter = accessor _localPidCounter (\ctr st -> st { _localPidCounter =
306localPidUnique :: Accessor LocalNodeState Int32
374localPidUnique :: Accessor LocalNodeState Int32
307localPidUnique = accessor _localPidUnique (\unq st -> st { _localPidUnique = unq })
375localPidUnique = accessor _localPidUnique (\unq st -> st { _localPidUnique = unq })
308
376
309−localMonitorCounter :: Accessor LocalNodeState Int32
310−localMonitorCounter = accessor _localMonitorCounter (\ctr st -> st { _localMonitorCounter = ctr })
311−
312localProcessWithId :: LocalProcessId -> Accessor LocalNodeState (Maybe LocalProcess)
377localProcessWithId :: LocalProcessId -> Accessor LocalNodeState (Maybe LocalProcess)
313localProcessWithId lpid = localProcesses >>> DAC.mapMaybe lpid
378localProcessWithId lpid = localProcesses >>> DAC.mapMaybe lpid
314
379
315connections :: Accessor LocalProcessState (Map ProcessId NT.Connection)
380connections :: Accessor LocalProcessState (Map ProcessId NT.Connection)
316connections = accessor _connections (\conns st -> st { _connections = conns })
381connections = accessor _connections (\conns st -> st { _connections = conns })
317
382
383+monitorCounter :: Accessor LocalProcessState Int32
384+monitorCounter = accessor _monitorCounter (\cnt st -> st { _monitorCounter = cnt })
385+
386+spawnCounter :: Accessor LocalProcessState Int32
387+spawnCounter = accessor _spawnCounter (\cnt st -> st { _spawnCounter = cnt })
388+
318connectionTo :: ProcessId -> Accessor LocalProcessState (Maybe NT.Connection)
389connectionTo :: ProcessId -> Accessor LocalProcessState (Maybe NT.Connection)
319connectionTo pid = connections >>> DAC.mapMaybe pid
390connectionTo pid = connections >>> DAC.mapMaybe pid
391+
392+
distributed-process/src/Control/Distributed/Process/Internal/NodeController.hs+3
@@ -104,6 +104,8 @@ nodeController = do
104 ncEffectNodeDied nid reason
104 ncEffectNodeDied nid reason
105 NCMsg _from (Died (Left pid) reason) ->
105 NCMsg _from (Died (Left pid) reason) ->
106 ncEffectProcessDied pid reason
106 ncEffectProcessDied pid reason
107+ NCMsg _from (Spawn _ _) ->
108+ fail "spawn not implemented"
107 -- Error cases
109 -- Error cases
108 NCMsg (Right _) (Link _) ->
110 NCMsg (Right _) (Link _) ->
109 error "Link message from a node?"
111 error "Link message from a node?"
@@ -305,6 +307,7 @@ destNid (Monitor pid _) = Just . processNodeId $ pid
305destNid (Unmonitor ref) = Just . processNodeId . monitorRefPid $ ref
307destNid (Unmonitor ref) = Just . processNodeId . monitorRefPid $ ref
306destNid (Died (Right _) _) = Nothing
308destNid (Died (Right _) _) = Nothing
307destNid (Died (Left _pid) _) = fail "destNid: TODO"
309destNid (Died (Left _pid) _) = fail "destNid: TODO"
310+destNid (Spawn _ _) = Nothing
308
311
309initNCState :: NCState
312initNCState :: NCState
310initNCState = NCState
313initNCState = NCState