@@ -89,6 +89,7 @@ import Control.Distributed.Process.Internal.StrictMVar
8989import Control.Concurrent.Chan (writeChan)
9090import Control.Concurrent.STM
9191 ( STM
92+ , TVar
9293 , atomically
9394 , orElse
9495 , newTVar
@@ -181,7 +182,7 @@ newChan = do
181182 let sport = SendPort cid
182183 chan <- liftIO newTQueueIO
183184 chan' <- mkWeakTQueue chan $ finalizer (processState proc) lcid
184− let rport = ReceivePortSingle chan
185+ let rport = ReceivePort $ readTQueue chan
185186 let tch = TypedChannel chan'
186187 return ( (channelCounter ^: (+ 1))
187188 . (typedChannelWithId lcid ^= Just tch)
@@ -215,35 +216,30 @@ receiveChanTimeout 0 ch = liftIO . atomically $
215216receiveChanTimeout n ch = liftIO . timeout n . atomically $
216217 receiveSTM ch
217218
218−-- | Receive a message from a typed channel as an STM transaction.
219−--
220−-- The transaction retries when no message is available.
221−receiveSTM :: ReceivePort a -> STM a
222−receiveSTM (ReceivePortSingle c) =
223− readTQueue 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)
230− return a
231− where
232− rotate :: [a] -> [a]
233− rotate [] = []
234− rotate (x:xs) = xs ++ [x]
235−
236219-- | Merge a list of typed channels.
237220--
238221-- The result port is left-biased: if there are messages available on more
239222-- than one port, the first available message is returned.
240223mergePortsBiased :: Serializable a => [ReceivePort a] -> Process (ReceivePort a)
241−mergePortsBiased = return . ReceivePortBiased
224+mergePortsBiased = return . ReceivePort. foldr1 orElse . map receiveSTM
242225
243226-- | Like 'mergePortsBiased', but with a round-robin scheduler (rather than
244227-- left-biased)
245228mergePortsRR :: Serializable a => [ReceivePort a] -> Process (ReceivePort a)
246−mergePortsRR ps = liftIO . atomically $ ReceivePortRR <$> newTVar ps
229+mergePortsRR = \ps -> do
230+ psVar <- liftIO . atomically $ newTVar (map receiveSTM ps)
231+ return $ ReceivePort (rr psVar)
232+ where
233+ rotate :: [a] -> [a]
234+ rotate [] = []
235+ rotate (x:xs) = xs ++ [x]
236+
237+ rr :: TVar [STM a] -> STM a
238+ rr psVar = do
239+ ps <- readTVar psVar
240+ a <- foldr1 orElse ps
241+ writeTVar psVar (rotate ps)
242+ return a
247243
248244--------------------------------------------------------------------------------
249245-- Advanced messaging --