caf - Concurrency Abstractions using Futures

caf
is a library providing several concurrency abstractions such as buffers, channels, bounded channels and quantity semaphores in Haskell. Its feature is the synchronisation of processes on implicit future values, an idea that was adopted from AliceML.

Features

Futures. Processes can synchronize on futures. Futures are expression that can be dealt as values even they are not evaluated. Once the future value is needed then the computation suspends on the evaluation of the future. There are several kinds of futures available in the package:

  • explicit futures: they must be forced to be evaluated explicitly.
  • implicit futures: they are automatically triggered.
  • lazy futures: they are evaluated in a lazy thread. That means, thread creation starts when the futures is needed.
  • strict future: they get immediately evaluated if the value is needed.That means, as soon as possible.
  • recursive futures: is like implicite futures with the difference, that the future is evaluated as the argument of the code.
  • lazy recursive futures: the recursive variant evaluated with a lazy strategy.
  • strict recursive futures: the recursive variant evaluated with a strict strategy.

Primitives. Our goal is to implement all kinds of concurrency primitives that are currently available in Control.Concurrent.*.  At this time, modules providing the following primitives are available:

  • 'Test and Set' on cells
  • Buffers
  • undbounded & bounded Channels
  • Quantity Semaphores
  • Barrier (limited)

Example

This example is included in the package.

--------------------------------------------------------------------------------
-- | Producer Consumer Example for channels using 'Futures.withFuturesDo'. -- | Main entry point of the example. channelExample implements a consumer producer -- | scenario without futures. channelExampleF uses futures for evaluation. channelExampleF :: IO ()
channelExampleF = Futures.withFuturesDo channelExample

-- | Producer Consumer Example for channels. -- | Main function. channelExample :: IO ()
channelExample = do putStrLn $ "Producer-Consumer example with channels" channel <- Chan.newChan
Control.Concurrent.forkIO $ (produce 10 channel) Control.Concurrent.forkIO $ (consume channel) -- now wait 10 seconds (because humans eyes are slow) Control.Concurrent.threadDelay $ 10 * 1000000

consume :: (Show a) => Chan.Chan a -> IO b
consume chan = do putStrLn $ "Trying to read..." val <- Chan.readChan chan
putStrLn $ "read new value: " ++ show val
--Control.Concurrent.threadDelay oneSecond consume chan produce :: (Num a) => a -> Chan.Chan a -> IO ()
produce n chan = do case n of 0 -> Chan.writeChan chan n
otherwise -> do Chan.writeChan chan n
--wait one second because the concurrent thread should have a try Control.Concurrent.threadDelay 1000000
produce (n-1) chan

Download

Installation is currently in the form of a Haskell Cabal package, which is available at HackageDB:

http://hackage.haskell.org/cgi-bin/hackage-scripts/package/caf

The package contains a README file that describes the installation process.

The package has been tested with GHC-6.8.2 on Linux.

Build & Install

1. Unzip the tarball
2. Navigate to the directory
3. Run the installation commands
  runhaskell Setup configure
  runhaskell Setup build
  sudo runhaskell Setup install

(others ways possible)

More Information

Read also the attached Paper. It explains the implementation of caf in a detailed manner.

Ċ
caf.pdf
(139k)
Martina Willig,
Mar 26, 2009, 5:59 AM