Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
Extra functions for Control.Concurrent.
This module includes three new types of MVar
, namely Lock
(no associated value),
Var
(never empty) and Barrier
(filled at most once). See
this blog post
for examples and justification.
If you need greater control of exceptions and threads see the slave-thread package. If you need elaborate relationships between threads see the async package.
Synopsis
- module Control.Concurrent
- withNumCapabilities :: Int -> IO a -> IO a
- once :: IO a -> IO (IO a)
- onceFork :: IO a -> IO (IO a)
- data Lock
- newLock :: IO Lock
- withLock :: Lock -> IO a -> IO a
- withLockTry :: Lock -> IO a -> IO (Maybe a)
- data Var a
- newVar :: a -> IO (Var a)
- readVar :: Var a -> IO a
- writeVar :: Var a -> a -> IO ()
- modifyVar :: Var a -> (a -> IO (a, b)) -> IO b
- modifyVar_ :: Var a -> (a -> IO a) -> IO ()
- withVar :: Var a -> (a -> IO b) -> IO b
- data Barrier a
- newBarrier :: IO (Barrier a)
- signalBarrier :: Partial => Barrier a -> a -> IO ()
- waitBarrier :: Barrier a -> IO a
- waitBarrierMaybe :: Barrier a -> IO (Maybe a)
Documentation
module Control.Concurrent
withNumCapabilities :: Int -> IO a -> IO a Source #
On GHC 7.6 and above with the -threaded
flag, brackets a call to setNumCapabilities
.
On lower versions (which lack setNumCapabilities
) this function just runs the argument action.
once :: IO a -> IO (IO a) Source #
Given an action, produce a wrapped action that runs at most once. If the function raises an exception, the same exception will be reraised each time.
let x ||| y = do t1 <- onceFork x; t2 <- onceFork y; t1; t2 \(x :: IO Int) -> void (once x) == pure () \(x :: IO Int) -> join (once x) == x \(x :: IO Int) -> (do y <- once x; y; y) == x \(x :: IO Int) -> (do y <- once x; y ||| y) == x
onceFork :: IO a -> IO (IO a) Source #
Like once
, but immediately starts running the computation on a background thread.
\(x :: IO Int) -> join (onceFork x) == x \(x :: IO Int) -> (do a <- onceFork x; a; a) == x
Lock
Like an MVar
, but has no value.
Used to guarantee single-threaded access, typically to some system resource.
As an example:
lock <-newLock
let output =withLock
. putStrLn forkIO $ do ...; output "hello" forkIO $ do ...; output "world"
Here we are creating a lock to ensure that when writing output our messages
do not get interleaved. This use of MVar
never blocks on a put. It is permissible,
but rare, that a withLock contains a withLock inside it - but if so,
watch out for deadlocks.
Var
Like an MVar
, but must always be full.
Used to operate on a mutable variable in a thread-safe way.
As an example:
hits <-newVar
0 forkIO $ do ...;modifyVar_
hits (+1); ... i <-readVar
hits print ("HITS",i)
Here we have a variable which we modify atomically, so modifications are
not interleaved. This use of MVar
never blocks on a put. No modifyVar
operation should ever block, and they should always complete in a reasonable
timeframe. A Var
should not be used to protect some external resource, only
the variable contained within. Information from a readVar
should not be subsequently
inserted back into the Var
.
modifyVar :: Var a -> (a -> IO (a, b)) -> IO b Source #
Modify a Var
producing a new value and a return result.
Barrier
Starts out empty, then is filled exactly once. As an example:
bar <-newBarrier
forkIO $ do ...; val <- ...;signalBarrier
bar val print =<<waitBarrier
bar
Here we create a barrier which will contain some computed value. A thread is forked to fill the barrier, while the main thread waits for it to complete. A barrier has similarities to a future or promise from other languages, has been known as an IVar in other Haskell work, and in some ways is like a manually managed thunk.
signalBarrier :: Partial => Barrier a -> a -> IO () Source #
Write a value into the Barrier, releasing anyone at waitBarrier
.
Any subsequent attempts to signal the Barrier
will throw an exception.
waitBarrier :: Barrier a -> IO a Source #
Wait until a barrier has been signaled with signalBarrier
.
waitBarrierMaybe :: Barrier a -> IO (Maybe a) Source #
A version of waitBarrier
that never blocks, returning Nothing
if the barrier has not yet been signaled.