| Copyright | (c) Joseph Adams 2012 |
|---|---|
| License | BSD3 |
| Maintainer | joeyadams3.14159@gmail.com |
| Portability | Requires GHC 7+ |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Control.Concurrent.STM.Delay
Description
One-shot timer whose duration can be updated. Think of it as an enhanced version of registerDelay.
This uses GHC.Event when available (GHC 7.2+, -threaded, non-Windows OS). Otherwise, it falls back to forked threads and threadDelay.
Managing delays
A Delay is an updatable timer that rings only once.
newDelay :: Int -> IO Delay Source #
Create a new Delay that will ring in the given number of microseconds.
updateDelay :: Delay -> Int -> IO () Source #
Set an existing Delay to ring in the given number of microseconds (from the time updateDelay is called), rather than when it was going to ring. If the Delay has already rung, do nothing.
cancelDelay :: Delay -> IO () Source #
Set a Delay so it will never ring, even if updateDelay is used later. If the Delay has already rung, do nothing.
Waiting for expiration
tryWaitDelayIO :: Delay -> IO Bool Source #
Faster version of . See atomically . tryWaitDelayreadTVarIO.
Since 0.1.1
Example
Suppose we are managing a network connection, and want to time it out if no messages are received in over five minutes. We'll create a Delay, and an action to "bump" it:
let timeoutInterval = 5 * 60 * 1000000 ::Intdelay <-newDelaytimeoutInterval let bump =updateDelaydelay timeoutInterval
This way, the Delay will ring if it is not bumped for longer than five minutes.
Now we fork the receiver thread:
dead <-newEmptyTMVarIO_ <-forkIO$ (forever$ do msg <- recvMessage bump handleMessage msg ) `finally`atomically(putTMVardead ())
Finally, we wait for the delay to ring, or for the receiver thread to fail due to an exception:
atomically$waitDelaydelay `orElse`readTMVardead
Warning:
- If handleMessage blocks, the
Delaymay ring due tohandleMessagetaking too long, rather than justrecvMessagetaking too long. - The loop will continue to run until you do something to stop it.
It might be simpler to use System.Timeout instead:
m <-timeouttimeoutInterval recvMessage case m of Nothing ->fail"timed out" Just msg -> handleMessage msg
However, using a Delay has the following advantages:
- If
recvMessagemakes a blocking FFI call (e.g. network I/O on Windows),timeoutwon't work, since it uses an asynchronous exception, and FFI calls can't be interrupted with async exceptions. TheDelayapproach lets you handle the timeout in another thread, while the FFI call is still blocked. updateDelayis more efficient thantimeoutwhen GHC.Event is available.