@@ -1,3 +1,5 @@
1+{-# LANGUAGE DeriveGeneric #-}
1-- | Types used throughout the Cloud Haskell framework
3-- | Types used throughout the Cloud Haskell framework
3-- We collect all types used internally in a single module because
5-- We collect all types used internally in a single module because
@@ -29,6 +31,7 @@ module Control.Distributed.Process.Internal.Types
29 , ReceivePort(..)
31 , ReceivePort(..)
30 -- * Messages
32 -- * Messages
31 , Message(..)
33 , Message(..)
32 , createMessage
35 , createMessage
33 , createUnencodedMessage
36 , createUnencodedMessage
34 , unsafeCreateUnencodedMessage
37 , unsafeCreateUnencodedMessage
@@ -77,7 +80,7 @@ module Control.Distributed.Process.Internal.Types
77import System.Mem.Weak (Weak)
80import System.Mem.Weak (Weak)
78import Data.Map (Map)
81import Data.Map (Map)
79import Data.Int (Int32)
82import Data.Int (Int32)
80−import Data.Typeable (Typeable)
83+import Data.Typeable (Typeable, typeOf)
81import Data.Binary (Binary(put, get), putWord8, getWord8, encode)
84import Data.Binary (Binary(put, get), putWord8, getWord8, encode)
82import qualified Data.ByteString as BSS (ByteString, concat, copy)
85import qualified Data.ByteString as BSS (ByteString, concat, copy)
83import qualified Data.ByteString.Lazy as BSL
86import qualified Data.ByteString.Lazy as BSL
@@ -90,6 +93,7 @@ import qualified Data.ByteString.Lazy as BSL
90import qualified Data.ByteString.Lazy.Internal as BSL (ByteString(..))
93import qualified Data.ByteString.Lazy.Internal as BSL (ByteString(..))
91import Data.Accessor (Accessor, accessor)
94import Data.Accessor (Accessor, accessor)
92import Control.Category ((>>>))
95import Control.Category ((>>>))
96+import Control.DeepSeq (NFData(..))
93import Control.Exception (Exception)
97import Control.Exception (Exception)
94import Control.Concurrent (ThreadId)
98import Control.Concurrent (ThreadId)
95import Control.Concurrent.Chan (Chan)
99import Control.Concurrent.Chan (Chan)
@@ -113,14 +117,19 @@ import Control.Distributed.Process.Internal.WeakTQueue (TQueue)
113import Control.Distributed.Static (RemoteTable, Closure)
117import Control.Distributed.Static (RemoteTable, Closure)
114import qualified Control.Distributed.Process.Internal.StrictContainerAccessors as DAC (mapMaybe)
118import qualified Control.Distributed.Process.Internal.StrictContainerAccessors as DAC (mapMaybe)
116--------------------------------------------------------------------------------
123--------------------------------------------------------------------------------
117-- Node and process identifiers --
124-- Node and process identifiers --
118--------------------------------------------------------------------------------
125--------------------------------------------------------------------------------
120-- | Node identifier
127-- | Node identifier
121newtype NodeId = NodeId { nodeAddress :: NT.EndPointAddress }
128newtype NodeId = NodeId { nodeAddress :: NT.EndPointAddress }
122− deriving (Eq, Ord, Binary, Typeable)
129+ deriving (Eq, Ord, Typeable, Generic)
123−
130+instance Binary NodeId where
131+instance NFData NodeId
132+instance Hashable NodeId where
124instance Show NodeId where
133instance Show NodeId where
125 show (NodeId addr) = "nid://" ++ show addr
134 show (NodeId addr) = "nid://" ++ show addr
@@ -130,7 +139,9 @@ data LocalProcessId = LocalProcessId
130 { lpidUnique :: {-# UNPACK #-} !Int32
139 { lpidUnique :: {-# UNPACK #-} !Int32
131 , lpidCounter :: {-# UNPACK #-} !Int32
140 , lpidCounter :: {-# UNPACK #-} !Int32
133− deriving (Eq, Ord, Typeable, Show)
142+ deriving (Eq, Ord, Typeable, Generic, Show)
144+instance Hashable LocalProcessId where
135-- | Process identifier
146-- | Process identifier
136data ProcessId = ProcessId
147data ProcessId = ProcessId
@@ -139,7 +150,11 @@ data ProcessId = ProcessId
139 -- | Node-local identifier for the process
150 -- | Node-local identifier for the process
140 , processLocalId :: {-# UNPACK #-} !LocalProcessId
151 , processLocalId :: {-# UNPACK #-} !LocalProcessId
142− deriving (Eq, Ord, Typeable)
153+ deriving (Eq, Ord, Typeable, Generic)
155+instance Binary ProcessId where
156+instance NFData ProcessId where
157+instance Hashable ProcessId where
144instance Show ProcessId where
159instance Show ProcessId where
145 show (ProcessId (NodeId addr) (LocalProcessId _ lid))
160 show (ProcessId (NodeId addr) (LocalProcessId _ lid))
@@ -150,7 +165,9 @@ data Identifier =
150 NodeIdentifier !NodeId
165 NodeIdentifier !NodeId
151 | ProcessIdentifier !ProcessId
166 | ProcessIdentifier !ProcessId
152 | SendPortIdentifier !SendPortId
167 | SendPortIdentifier !SendPortId
153− deriving (Eq, Ord)
168+ deriving (Eq, Ord, Generic)
170+instance Hashable Identifier where
155instance Show Identifier where
172instance Show Identifier where
156 show (NodeIdentifier nid) = show nid
173 show (NodeIdentifier nid) = show nid
@@ -276,8 +293,9 @@ data SendPortId = SendPortId {
276 -- | Process-local ID of the channel
293 -- | Process-local ID of the channel
277 , sendPortLocalId :: {-# UNPACK #-} !LocalSendPortId
294 , sendPortLocalId :: {-# UNPACK #-} !LocalSendPortId
279− deriving (Eq, Ord)
296+ deriving (Eq, Ord, Typeable, Generic)
298+instance Hashable SendPortId where
281instance Show SendPortId where
299instance Show SendPortId where
282 show (SendPortId (ProcessId (NodeId addr) (LocalProcessId _ plid)) clid)
300 show (SendPortId (ProcessId (NodeId addr) (LocalProcessId _ plid)) clid)
283 = "cid://" ++ show addr ++ ":" ++ show plid ++ ":" ++ show clid
301 = "cid://" ++ show addr ++ ":" ++ show plid ++ ":" ++ show clid
@@ -289,7 +307,11 @@ newtype SendPort a = SendPort {
289 -- | The (unique) ID of this send port
307 -- | The (unique) ID of this send port
290 sendPortId :: SendPortId
308 sendPortId :: SendPortId
292− deriving (Typeable, Binary, Show, Eq, Ord)
310+ deriving (Typeable, Generic, Show, Eq, Ord)
312+instance (Serializable a) => Binary (SendPort a) where
313+instance (Hashable a) => Hashable (SendPort a) where
314+instance (NFData a) => NFData (SendPort a) where
294-- | The receive end of a typed channel (not serializable)
316-- | The receive end of a typed channel (not serializable)
@@ -329,7 +351,19 @@ data Message =
330instance Show Message where
352instance Show Message where
331 show (EncodedMessage fp enc) = show enc ++ " :: " ++ showFingerprint fp []
353 show (EncodedMessage fp enc) = show enc ++ " :: " ++ showFingerprint fp []
332− show (UnencodedMessage fp _) = "[unencoded message] :: " ++ (showFingerprint fp [])
354+ show (UnencodedMessage _ uenc) = "[unencoded message] :: " ++ (show $ typeOf uenc)
356+-- | /internal use only/.
357+isEncoded :: Message -> Bool
358+isEncoded (EncodedMessage _ _) = True
361+-- This is just as internal as it looks and yes, it does feel a bit odd that
362+-- we're exporting it for use, however DPP does a /lot/ of work with low
363+-- level APIs such as unwrapMessage and handleMessage, and in the process
364+-- tries very hard to avoid copying (and re-serialisation) where possible.
365+-- Being able to determine that a message is encoded (or otherwise) makes
366+-- that a lot more manageable.
334-- | Turn any serialiable term into a message
368-- | Turn any serialiable term into a message
335createMessage :: Serializable a => a -> Message
369createMessage :: Serializable a => a -> Message
@@ -377,7 +411,8 @@ data MonitorRef = MonitorRef
377 -- | Unique to distinguish multiple monitor requests by the same process
411 -- | Unique to distinguish multiple monitor requests by the same process
378 , monitorRefCounter :: !Int32
412 , monitorRefCounter :: !Int32
380− deriving (Eq, Ord, Show)
414+ deriving (Eq, Ord, Show, Generic)
415+instance Hashable MonitorRef where
382-- | Message sent by process monitors
417-- | Message sent by process monitors
383data ProcessMonitorNotification =
418data ProcessMonitorNotification =
@@ -531,10 +566,6 @@ instance Binary LocalProcessId where
531 put lpid = put (lpidUnique lpid) >> put (lpidCounter lpid)
566 put lpid = put (lpidUnique lpid) >> put (lpidCounter lpid)
532 get = LocalProcessId <$> get <*> get
567 get = LocalProcessId <$> get <*> get
534−instance Binary ProcessId where
535− put pid = put (processNodeId pid) >> put (processLocalId pid)
536− get = ProcessId <$> get <*> get
538instance Binary ProcessMonitorNotification where
569instance Binary ProcessMonitorNotification where
539 put (ProcessMonitorNotification ref pid reason) = put ref >> put pid >> put reason
570 put (ProcessMonitorNotification ref pid reason) = put ref >> put pid >> put reason
540 get = ProcessMonitorNotification <$> get <*> get <*> get
571 get = ProcessMonitorNotification <$> get <*> get <*> get
@@ -567,7 +598,7 @@ instance Binary ProcessSignal where
567 put (NamedSend label msg) = putWord8 8 >> put label >> put (messageToPayload msg)
598 put (NamedSend label msg) = putWord8 8 >> put label >> put (messageToPayload msg)
568 put (Kill pid reason) = putWord8 9 >> put pid >> put reason
599 put (Kill pid reason) = putWord8 9 >> put pid >> put reason
569 put (Exit pid reason) = putWord8 10 >> put pid >> put (messageToPayload reason)
600 put (Exit pid reason) = putWord8 10 >> put pid >> put (messageToPayload reason)
570− put (LocalSend to msg) = putWord8 11 >> put to >> put (messageToPayload msg)
601+ put (LocalSend to' msg) = putWord8 11 >> put to' >> put (messageToPayload msg)
571 put (LocalPortSend sid msg) = putWord8 12 >> put sid >> put (messageToPayload msg)
602 put (LocalPortSend sid msg) = putWord8 12 >> put sid >> put (messageToPayload msg)
572 put (GetInfo about) = putWord8 30 >> put about
603 put (GetInfo about) = putWord8 30 >> put about
573 put (SigShutdown) = putWord8 31
604 put (SigShutdown) = putWord8 31
@@ -615,6 +646,9 @@ instance Binary SendPortId where
615 put cid = put (sendPortProcessId cid) >> put (sendPortLocalId cid)
646 put cid = put (sendPortProcessId cid) >> put (sendPortLocalId cid)
616 get = SendPortId <$> get <*> get
647 get = SendPortId <$> get <*> get
649+instance NFData SendPortId where
650+ rnf cid = (sendPortProcessId cid) `seq` (sendPortLocalId cid) `seq` ()
618instance Binary Identifier where
652instance Binary Identifier where
619 put (ProcessIdentifier pid) = putWord8 0 >> put pid
653 put (ProcessIdentifier pid) = putWord8 0 >> put pid
620 put (NodeIdentifier nid) = putWord8 1 >> put nid
654 put (NodeIdentifier nid) = putWord8 1 >> put nid
@@ -667,7 +701,7 @@ localProcessWithId :: LocalProcessId -> Accessor LocalNodeState (Maybe LocalProc
667localProcessWithId lpid = localProcesses >>> DAC.mapMaybe lpid
701localProcessWithId lpid = localProcesses >>> DAC.mapMaybe lpid
669localConnectionBetween :: Identifier -> Identifier -> Accessor LocalNodeState (Maybe (NT.Connection, ImplicitReconnect))
703localConnectionBetween :: Identifier -> Identifier -> Accessor LocalNodeState (Maybe (NT.Connection, ImplicitReconnect))
670−localConnectionBetween from to = localConnections >>> DAC.mapMaybe (from, to)
704+localConnectionBetween from' to' = localConnections >>> DAC.mapMaybe (from', to')
672monitorCounter :: Accessor LocalProcessState Int32
706monitorCounter :: Accessor LocalProcessState Int32
673monitorCounter = accessor _monitorCounter (\cnt st -> st { _monitorCounter = cnt })
707monitorCounter = accessor _monitorCounter (\cnt st -> st { _monitorCounter = cnt })