pooled-io 0.0.1.2 → 0.0.2
raw patch · 2 files changed
+89/−3 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Control.Concurrent.PooledIO.Sequence: async :: In -> IO () -> IO ()
+ Control.Concurrent.PooledIO.Sequence: data In
+ Control.Concurrent.PooledIO.Sequence: data Out
+ Control.Concurrent.PooledIO.Sequence: new :: IO (In, Out)
+ Control.Concurrent.PooledIO.Sequence: run :: Out -> IO ()
+ Control.Concurrent.PooledIO.Sequence: sync :: In -> IO a -> IO a
Files
pooled-io.cabal view
@@ -1,5 +1,5 @@ Name: pooled-io-Version: 0.0.1.2+Version: 0.0.2 License: BSD3 License-File: LICENSE Author: Henning Thielemann <haskell@henning-thielemann.de>@@ -26,6 +26,12 @@ * "Control.Concurrent.PooledIO.InOrder": run jobs in parallel with data dependencies like @make -j n@ .+ Additionally there is the module+ "Control.Concurrent.PooledIO.Sequence"+ that helps to serialize I/O actions from multiple threads.+ It is certainly most useful in connection with+ "Control.Concurrent.PooledIO.Independent".+ . Related packages: . * @lazyio@: interleave IO actions in a single thread@@ -34,7 +40,7 @@ but do not throttle concurrency with respect to number of available cores . * @parallel-tasks@:-Tested-With: GHC==7.4.1+Tested-With: GHC==7.4.2, GHC==7.8.4, GHC==7.10.1 Cabal-Version: >=1.8 Build-Type: Simple @@ -43,7 +49,7 @@ default: False Source-Repository this- Tag: 0.0.1.2+ Tag: 0.0.2 Type: darcs Location: http://code.haskell.org/~thielema/pooled-io/ @@ -67,6 +73,7 @@ Control.Concurrent.PooledIO.Independent Control.Concurrent.PooledIO.Final Control.Concurrent.PooledIO.InOrder+ Control.Concurrent.PooledIO.Sequence Other-Modules: Control.Concurrent.PooledIO.Monad
+ src/Control/Concurrent/PooledIO/Sequence.hs view
@@ -0,0 +1,79 @@+{- |+Functions for sequencing actions requested from concurrent threads.++Here is an example usage:++> import qualified Control.Concurrent.PooledIO.Independent as Parallel+> import qualified Control.Concurrent.PooledIO.Sequence as Sequence+>+> thread :: Sequence.In -> FilePath -> IO ()+> thread seqIn name = do+> txt <- Sequence.sync seqIn $ readFile (name ++ ".in")+> -- evaluate result with ($!!) before sending it to the sequencing thread+> Sequence.async seqIn . writeFile (name ++ ".out") $!! processMyText txt+> doFurtherStuff+> -- block main program until completion+> Sequence.sync seqIn $ return ()+>+> main :: IO ()+> main = do+> (seqIn, seqOut) <- Sequence.new+> void $ forkIO $ Sequence.run seqOut+> Parallel.run $ map (thread seqIn) ["a", "b", "c"]+-}+module Control.Concurrent.PooledIO.Sequence (In, Out, new, run, async, sync) where++import qualified Control.Concurrent.Split.Chan as Chan+import qualified Control.Concurrent.Split.MVar as MVar++import Control.Monad (join, forever)++import Data.Tuple.HT (mapPair)+++type Action = IO ()++newtype In = In (Chan.In Action)+newtype Out = Out (Chan.Out Action)+++new :: IO (In, Out)+new = fmap (mapPair (In,Out)) Chan.new++{- |+Run the sequencing thread.+You will usually fork it.+-}+run :: Out -> IO ()+run (Out chan) =+ forever $ join $ Chan.read chan++{- |+This is primarily intended for output functions.+You should make sure that the emitted data is evaluated before calling 'async'.+Otherwise the sequencing thread will evaluate it+and thus not much parallelization will happen.++Example:++> async seqIn . writeFile "foobar.txt" $!! show result+-}+async :: In -> IO () -> IO ()+async (In chan) act =+ Chan.write chan act++{- |+This is primarily intended for input functions.+You should also call it at the end of a thread in order to make sure+that all your asynchronous actions are completed.+It will actually also wait for the actions that were requested by other threads.+However, I think this should not hurt+since after completion of the current thread+another one will be started and it will certainly begin with an input action,+which has to be queued anyway.+-}+sync :: In -> IO a -> IO a+sync chan act = do+ (resultIn, resultOut) <- MVar.newEmpty+ async chan $ act >>= MVar.put resultIn+ MVar.take resultOut