-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A library of Concurrency Abstractions using Futures. -- -- This library contains implementations of several kinds of futures and -- concurrency abstractions. @package caf @version 0.0.3 -- | This module implements explicit futures (EFuture, -- efuture, force) as well as several variants of implicit -- futures (future, recursiveFuture, strictFuture, -- strictRecursiveFuture, lazyFuture, -- lazyRecursiveFuture) While explicit futures must be forced -- (using force) if their value is needed, this is not necessary -- for implicit futures. For implicit futures it is necessary to put them -- into the global wrapper withFuturesDo. module Control.Concurrent.Futures.Futures -- | The type EFuture implements explicit futures, i.e. if the value -- of the future is need it must be forced explicitly using force type EFuture a = MVar a -- | efuture creates an explicit future, i.e. the computation is -- performed concurrently. The future value can be forced using -- force efuture :: IO a -> IO (EFuture a) -- | force forces the value of an explicit future (EFuture), -- i.e. the calling thread blocks until the result becomes available. force :: EFuture a -> IO a -- | future creates an implicit future. A non-blocking concurrent -- computation is started. If the value of the future is needed, then the -- future will be forced implicitly. The concurrent computation is killed -- if the calling thread stops, even if future is used within -- withFuturesDo. future :: IO a -> IO a -- | recursiveFuture behaves similar to future with the -- difference that the future is recursive, i.e. the future created by -- recursiveFuture is used as argument of the code of the future. recursiveFuture :: (a -> IO a) -> IO a -- | withFuturesDo is the global wrapper which should be used around -- the code involving futures. I.e., instead of writing -- main=code one should use main=withFuturesDo code. -- Note, that there should be only one call to withFuturesDo in a -- program. withFuturesDo :: IO () -> IO () -- | creating a strict future is similar to future with the -- difference that if used inside withFuturesDo it is guaranteed -- that the concurrent computation is forced (and finished) before the -- main thread terminates. Warning: strictFuture should only be -- used within the global wrapper withFuturesDo! strictFuture :: IO a -> IO a -- | a recursive variant of strictFuture (see recursiveFuture -- and 'future) Warning: strictRecursiveFuture should only be used -- within the global wrapper withFuturesDo! strictRecursiveFuture :: (a -> IO a) -> IO a -- | a lazy future. Initially, no concurrent computation is started, but if -- the lazy future gets (implicitly) forced, then the lazy future becomes -- a strict future. Warning: lazyFuture should only be used within -- the global wrapper withFuturesDo! lazyFuture :: IO a -> IO a -- | a recursive variant of lazyFuture (see recursiveFuture -- and 'future) Warning: lazyRecursiveFuture should only be used -- within the global wrapper withFuturesDo! lazyRecursiveFuture :: (a -> IO a) -> IO a -- | binds a handle to its value. hbind :: (t -> t1) -> t -> t1 -- | creates a new handle. newhandled :: IO (a -> IO (), a) -- | a new handle component. bhandle :: (a -> (a -> IO ()) -> t) -> IO t -- | This module implements one-place buffers using futures. Warning: All -- operations on buffers should only be used within the global wrapper -- function withFuturesDo! module Control.Concurrent.Futures.Buffer -- | The buffer type contains of 3 cells and a handle. The first 2 cells -- are for communication of either a put or get is allowed. The thrist -- cell is the storage cell, the last cell contains a the active handle. type Buffer a = (Cell Bool, Cell Bool, Cell a, Cell (Bool -> IO ())) -- | Creates a new empty buffer. newBuf :: IO (Buffer a) -- | Puts a new value to a buffer. putBuf blocks if the buffer is -- full. putBuf :: Buffer a -> a -> IO () -- | Gets the contents of a non-empty buffer. If the buffer is empty, then -- this function blocks until the buffer is filled. getBuf :: Buffer a -> IO a -- | This module implements a channel synchronisation primitive using -- buffers that block on futures. A channel is a linked list of buffers. -- It has a read-end at one side and a write-end at the other. Elements -- put into the channel can be read out in a first in, first out order. A -- read and a write operation can be executed in parallel by several -- threads. A channel has no capacity bounding. -- -- The module contains similar functions as -- Control.Concurrent.Futures.Chan. -- -- Warning: All operations on channels should only be used within the -- global wrapper function Futures.withFuturesDo! module Control.Concurrent.Futures.Chan -- | A channel consists of a read-end buffer and a write-end buffer. The -- Itemtype is required to link the buffers in the channel. data Chan a type ChanType a = (Buffer (ItemType a), Buffer (ItemType a)) -- | Creates a new empty channel. newChan :: IO (Chan a) -- | Writes one value to a channel. A writeChan never blocks, since -- channels have no bounding limiters. writeChan :: Chan a -> a -> IO () -- | Reads out an item from the read-head of the channel. It blocks on a -- empty channel. readChan :: Chan a -> IO a -- | Implements the same behaviour as writeChanContents from the module -- Control.Concurrent.Chan. writeChanContents :: Chan a -> [a] -> IO () -- | Implements the same behaviour as getChanContents from the module -- Control.Concurrent.Chan. It reads permanently from the channel. getChanContents :: Chan a -> IO [a] -- | Writes two equally typed lists to a given channel in parallel. mergeChan :: [a] -> [a] -> Chan a -> IO (Chan a) -- | This module implements a quantity semaphore using buffers that block -- on futures. -- -- A QSem equals to QSemN in Control.Concurrent. A Buffer equals to QSem -- in Control.Concurrent. -- -- Warning: All operations on quantity semaphores should only be used -- within the global wrapper function Futures.withFuturesDo! module Control.Concurrent.Futures.QSem -- | A quantity semaphores contains of a capacity and a waiting queue -- containing buffers. type QSem = Buffer (Int, [Buffer Bool]) -- | Creates a new quantity semaphore of capacity cnt. newQSem :: Int -> IO (Buffer (Int, [Buffer Bool])) -- | Increments the semaphore's value, if there are no waiters. up -- reads out of the waiting queue and writes True into a waiting -- Buffer. Note: This operation equals to signalQSemN in -- Control.Concurrent.QSemN. up :: QSem -> IO () -- | Decrements the semaphore's value. If the value has already reached -- zero, then down creates a new empty Buffer that is being -- added to the semaphore's waiting queue. It blocks until the buffer -- gets filled by a up. Note: This operation equals to waitQSemN -- in Control.Concurrent.QSemN. down :: QSem -> IO Bool -- | Use the quantity semaphore to limit the computation of code. This -- function performs a down on the given q. s., executues the code and -- returns after a up on the q.s. . enter :: QSem -> IO a -> IO () -- | This modules combines a quantity semaphore from the module -- Control.Concurrent.Fututes.QSem and a channel from module -- Control.Concurrent.Fututes.Chan to a new synchronisation primitive. -- Bounded channels have a limited capacity of storage cells. Warning: -- All operations on bounded channels should only be used within the -- global wrapper function Futures.withFuturesDo! module Control.Concurrent.Futures.BChan type BChan a = (Chan a, QSem) -- | Creates a new bounded channel newBChan :: Int -> IO (BChan a) -- | Performs an up-operation on the QSem of the bounded channel and then -- reads a value from the channel. The read operation may block. readBChan :: BChan a -> IO a -- | Performs a down-operations on the QSem of the bounded channel and -- writes a new value to it. The down-operation may block. writeBChan :: BChan a -> a -> IO () -- | This module implements a quantity semaphore using handles that block -- on futures. A HQSem equals to QSemN in Control.Concurrent. A Buffer -- euqals to QSem in Control.Concurrent. Warning: All operations on -- quantity semaphores should only be used within the global wrapper -- function withFuturesDo! module Control.Concurrent.Futures.HQSem -- | A handled quantity semaphores contains of a capacity and a waiting -- queue containing handles. type HQSem = Buffer (Int, [Bool -> IO ()]) -- | Creates a new quantity semaphore of capacity cnt. newHQSem :: Int -> IO (HQSem) -- | Increments the semaphore's value, if there are no waiters. up -- reads out of the waiting queue and binds a waiting handle to True. -- Note: This operation equals to signalQSemN in -- Control.Concurrent.QSemN. upHQSem :: HQSem -> IO () -- | Decrements the semaphore's value. If the value has already reached 0, -- then down creates a new handle that is being added to the -- semaphore's waiting queue. It blocks until the handle assigns a value -- to its future by a up. Note: This operation equals to -- waitQSemN in Control.Concurrent.QSemN. downHQSem :: HQSem -> IO (Bool) -- | This module implements barrier using futures. A rendezvous ensures -- that two threads meet at a specific point before continuing their -- computation. The rendezvous idiom blocks at this point until both -- threads have arrived. A barrier is a rendezvous for a group of -- processes. Assume that a application is divided into phases where a -- couple of threads compute several interims to be the input for the -- next phase. Then all threads must complete the current phase before -- entering the next. To achieve this behaviour a barrier is placed at -- the end of a phase. Note that a barriers is purely for synchronisation -- and not for exchange of data. -- -- Warning: All operations on barrier should only be used within the -- global wrapper function withFuturesDo! module Control.Concurrent.Futures.Barrier -- | A new barrier type contains of a buffer containing the count of active -- threads, a buffer containing the a count of finished threads and a -- capacity. type Bar a = (Buffer a, Buffer [Bool -> IO ()], Int) -- | Creates a new barrier. newBar :: Int -> IO (Buffer Int, Buffer [Bool -> IO ()], Int) -- | syncs on the barrier syncBar :: (Buffer Int, Buffer [Bool -> IO ()], Int) -> IO Bool -- | This package implements futures and various kinds of concurrency -- abstractions using futures. -- -- Threads can synchronise their values via futures. Future values are -- lazily evaluated so they explicitly suspend the computation. Each -- future object is associated with a background thread that computes the -- future value. As long as this expression has not been evaluated, the -- value of the future is unknown. Whenever an unknown future is accessed -- the computation will suspend on this future. Once the value has been -- evaluated the computation resumes. A handle is a component that points -- to an unevaluated future and computes its value on demand. Therefore, -- handles are used to associate a value to a future. They provide a -- synchronisation mechanism for processes. -- -- Example This example shows how you can use Buffer to -- concurrently compute the values of nodes from a binary tree. -- --
--   data BTree a = BLeaf a | BNode a (BTree a) (BTree a)
--   
-- --
--   concSumB :: (Num a) => BTree a -> IO a
--   concSumB t = do 
--     result <- newBuf
--     case t of
--       BLeaf a -> putBuf result a;
--       BNode a t1 t2 -> sumB result t 
--     out <- getBuf result
--     return out
--   
-- --
--   sumB :: (Num a) => Buffer a -> BTree a -> IO ()
--   sumB mvar tree = do 
--    case tree of 
--      BLeaf a -> putBuf mvar a 
--      BNode a t1 t2 -> do
--   			sem <- newBuf
--   			forkIO (sumB sem t1)
--   			forkIO (sumB sem t2)
--   			erg1 <-getBuf sem
--   			erg2 <-getBuf sem 
--   			putBuf mvar (erg1 + erg2 + a)
--   
-- -- You can test the function with the following test data -- --
--   bintree = BNode 1 (BNode 24 (BLeaf 2) (BNode 6 (BLeaf 24) (BLeaf 3)))(BNode 33 (BLeaf 7) (BLeaf 8))
--   concSumB bintree
--   
module Control.Concurrent.Futures