@@ -54,6 +54,7 @@ module Control.Distributed.Process.Internal.Primitives
55 -- * Auxiliary API
55 -- * Auxiliary API
56 , expectTimeout
56 , expectTimeout
57 , spawnAsync
58 , spawnAsync
58 , linkNode
59 , linkNode
59 , linkPort
60 , linkPort
@@ -74,6 +75,7 @@ import Data.Binary (decode)
74import Data.Time.Clock (getCurrentTime)
75import Data.Time.Clock (getCurrentTime)
75import Data.Time.Format (formatTime)
76import Data.Time.Format (formatTime)
76import System.Locale (defaultTimeLocale)
77import System.Locale (defaultTimeLocale)
78+import System.Timeout (timeout)
77import Control.Monad.Reader (ask)
79import Control.Monad.Reader (ask)
78import Control.Monad.IO.Class (MonadIO, liftIO)
80import Control.Monad.IO.Class (MonadIO, liftIO)
79import Control.Applicative ((<$>))
81import Control.Applicative ((<$>))
@@ -188,7 +190,7 @@ newChan = do
190 finalizer :: StrictMVar LocalProcessState -> LocalSendPortId -> IO ()
192 finalizer :: StrictMVar LocalProcessState -> LocalSendPortId -> IO ()
191− finalizer processState lcid = modifyMVar_ processState $
193+ finalizer st lcid = modifyMVar_ st $
192 return . (typedChannelWithId lcid ^= Nothing)
194 return . (typedChannelWithId lcid ^= Nothing)
194-- | Send a message on a typed channel
196-- | Send a message on a typed channel
@@ -204,18 +206,29 @@ sendChan (SendPort cid) msg = do
204-- | Wait for a message on a typed channel
206-- | Wait for a message on a typed channel
205receiveChan :: Serializable a => ReceivePort a -> Process a
207receiveChan :: Serializable a => ReceivePort a -> Process a
206receiveChan = liftIO . atomically . receiveSTM
208receiveChan = liftIO . atomically . receiveSTM
208− receiveSTM :: ReceivePort a -> STM a
209− receiveSTM (ReceivePortSingle c) =
211− receiveSTM (ReceivePortBiased ps) =
212− foldr1 orElse (map receiveSTM ps)
213− receiveSTM (ReceivePortRR psVar) = do
214− ps <- readTVar psVar
215− a <- foldr1 orElse (map receiveSTM ps)
216− writeTVar psVar (rotate ps)
210+-- | Like 'receiveChan' but with a timeout. If the timeout is 0, do a
211+-- non-blocking check for a message.
212+receiveChanTimeout :: Serializable a => Int -> ReceivePort a -> Process (Maybe a)
213+receiveChanTimeout 0 ch = liftIO . atomically $
214+ (Just <$> receiveSTM ch) `orElse` return Nothing
215+receiveChanTimeout n ch = liftIO . timeout n . atomically $
218+-- | Receive a message from a typed channel as an STM transaction.
220+-- The transaction retries when no message is available.
221+receiveSTM :: ReceivePort a -> STM a
222+receiveSTM (ReceivePortSingle c) =
224+receiveSTM (ReceivePortBiased ps) =
225+ foldr1 orElse (map receiveSTM ps)
226+receiveSTM (ReceivePortRR psVar) = do
227+ ps <- readTVar psVar
228+ a <- foldr1 orElse (map receiveSTM ps)
229+ writeTVar psVar (rotate ps)
219 rotate :: [a] -> [a]
232 rotate :: [a] -> [a]
220 rotate [] = []
233 rotate [] = []
221 rotate (x:xs) = xs ++ [x]
234 rotate (x:xs) = xs ++ [x]
@@ -459,7 +472,7 @@ finally a sequel = bracket_ (return ()) sequel a
460-- | Like 'expect' but with a timeout
473-- | Like 'expect' but with a timeout
461expectTimeout :: forall a. Serializable a => Int -> Process (Maybe a)
474expectTimeout :: forall a. Serializable a => Int -> Process (Maybe a)
462−expectTimeout timeout = receiveTimeout timeout [match return]
475+expectTimeout n = receiveTimeout n [match return]
464-- | Asynchronous version of 'spawn'
477-- | Asynchronous version of 'spawn'