Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Haddock comments, and add module Workers
- Loading branch information
Dan Rosén
committed
Feb 7, 2013
1 parent
c52ac72
commit 4c92a53
Showing
7 changed files
with
134 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,75 @@ | ||
{-# LANGUAGE DeriveFunctor #-} | ||
-- | Promises that allow spawning and cancelling in `IO`, and an `STM` result | ||
module Control.Concurrent.STM.Promise | ||
( Promise(..), an | ||
, PromiseResult(..) | ||
, isAn, isUnfinished, isCancelled | ||
, eitherResult, bothResults, manyResults | ||
, eitherResult, bothResults | ||
) where | ||
|
||
import Control.Monad.STM | ||
|
||
-- | A promise | ||
data Promise a = Promise | ||
{ spawn :: IO () | ||
-- ^ Instruction for spawning | ||
, cancel :: IO () | ||
-- ^ Instruction for cancelling | ||
, result :: STM (PromiseResult a) | ||
-- ^ The result of a computation | ||
} | ||
deriving Functor | ||
|
||
-- | The result of the promise | ||
data PromiseResult a | ||
= Unfinished | ||
-- ^ Not finished yet (or not even spawned yet)) | ||
| Cancelled | ||
-- ^ Cancelled | ||
| An a | ||
-- ^ A result | ||
deriving (Functor, Eq, Ord, Show) | ||
|
||
-- | Gets the result (partial function) | ||
an :: PromiseResult a -> a | ||
an (An a) = a | ||
an _ = error "an: on non-An result!" | ||
|
||
-- | Is this a result? | ||
isAn :: PromiseResult a -> Bool | ||
isAn An{} = True | ||
isAn _ = False | ||
|
||
-- | Is this unfinished? | ||
isUnfinished :: PromiseResult a -> Bool | ||
isUnfinished Unfinished{} = True | ||
isUnfinished _ = False | ||
|
||
-- | Is this cancelled? | ||
isCancelled :: PromiseResult a -> Bool | ||
isCancelled Cancelled{} = True | ||
isCancelled _ = False | ||
|
||
-- | If either is finished (`An`), return one of them (favor the first one) | ||
-- | ||
-- If either is `Unfinished`, this is also `Unfinished`. | ||
-- | ||
-- Otherwise, both are `Cancelled` and so is this. | ||
eitherResult :: PromiseResult a -> PromiseResult a -> PromiseResult a | ||
eitherResult (An a) _ = An a | ||
eitherResult _ (An e) = An e | ||
eitherResult Unfinished _ = Unfinished | ||
eitherResult _ Unfinished = Unfinished | ||
eitherResult _ _ = Cancelled | ||
|
||
bothResults :: PromiseResult a -> PromiseResult a -> PromiseResult (a,a) | ||
-- | If both are finished (`An`), return them in a tuple. | ||
-- | ||
-- If either is `Cancelled`, this is also `Cancelled`. | ||
-- | ||
-- Otherwise, both are `Unfinished` and so is this. | ||
bothResults :: PromiseResult a -> PromiseResult b -> PromiseResult (a,b) | ||
bothResults (An a) (An e) = An (a,e) | ||
bothResults Cancelled _ = Cancelled | ||
bothResults _ Cancelled = Cancelled | ||
bothResults _ _ = Unfinished | ||
|
||
manyResults :: PromiseResult a -> PromiseResult a -> PromiseResult (Either a (a,a)) | ||
manyResults (An a) (An e) = An $ Right (a,e) | ||
manyResults (An a) _ = An $ Left a | ||
manyResults _ (An e) = An $ Left e | ||
manyResults Unfinished _ = Unfinished | ||
manyResults _ Unfinished = Unfinished | ||
manyResults _ _ = Cancelled | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
-- | Evaluating promises in parallel | ||
module Control.Concurrent.STM.Promise.Workers (workers,worker,evaluatePromise) where | ||
|
||
import Control.Concurrent | ||
import Control.Concurrent.STM | ||
import Control.Concurrent.STM.Promise | ||
import Control.Monad | ||
|
||
maybeIO :: Maybe a -> (a -> IO b) -> IO (Maybe b) | ||
maybeIO m f = maybe (return Nothing) (fmap Just . f) m | ||
|
||
-- | Evaluates a single promise, maybe using a timeout in microseconds. | ||
evaluatePromise :: Maybe Int -> Promise a -> IO () | ||
evaluatePromise m_t promise = do | ||
m_thr <- maybeIO m_t $ \ timeout -> forkIO $ do | ||
threadDelay timeout | ||
cancel promise | ||
|
||
spawn promise | ||
|
||
atomically $ do | ||
status <- result promise | ||
when (isUnfinished status) retry | ||
|
||
void $ maybeIO m_thr killThread | ||
|
||
-- | Evaluates a channel of promises, maybe using a timeout in microseconds. | ||
-- Stops when the channel is empty. | ||
worker :: Maybe Int -> TChan (Promise a) -> IO () | ||
worker m_t ch = go where | ||
go = do | ||
m_promise <- atomically $ tryReadTChan ch | ||
case m_promise of | ||
Just promise -> evaluatePromise m_t promise >> go | ||
Nothing -> return () | ||
|
||
|
||
-- | Evaluate these promises on n processors, maybe using a timeout in microseconds. | ||
workers :: Maybe Int -> Int -> [Promise a] -> IO () | ||
workers m_t n xs = do | ||
ch <- newTChanIO | ||
atomically $ mapM_ (writeTChan ch) xs | ||
replicateM_ n $ forkIO $ worker m_t ch | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.