diff options
Diffstat (limited to 'InterruptibleDelay.hs')
-rw-r--r-- | InterruptibleDelay.hs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/InterruptibleDelay.hs b/InterruptibleDelay.hs new file mode 100644 index 00000000..d59ec8ef --- /dev/null +++ b/InterruptibleDelay.hs | |||
@@ -0,0 +1,41 @@ | |||
1 | module InterruptibleDelay where | ||
2 | |||
3 | import Control.Concurrent | ||
4 | import Control.Monad | ||
5 | import Control.Exception ({-evaluate,-}handle,ErrorCall(..)) | ||
6 | import Data.Time.Clock (NominalDiffTime) | ||
7 | |||
8 | type Microseconds = Int | ||
9 | |||
10 | microseconds :: NominalDiffTime -> Microseconds | ||
11 | microseconds d = round $ 1000000 * d | ||
12 | |||
13 | data InterruptibleDelay = InterruptibleDelay | ||
14 | { delayThread :: MVar ThreadId | ||
15 | } | ||
16 | |||
17 | interruptibleDelay :: IO InterruptibleDelay | ||
18 | interruptibleDelay = do | ||
19 | fmap InterruptibleDelay newEmptyMVar | ||
20 | |||
21 | startDelay :: InterruptibleDelay -> Microseconds -> IO Bool | ||
22 | startDelay d interval = do | ||
23 | thread <- myThreadId | ||
24 | handle (\(ErrorCall _)-> do | ||
25 | debugNoise $ "delay interrupted" | ||
26 | return False) $ do | ||
27 | putMVar (delayThread d) thread | ||
28 | threadDelay interval | ||
29 | void $ takeMVar (delayThread d) | ||
30 | return True | ||
31 | |||
32 | where debugNoise str = return () | ||
33 | |||
34 | |||
35 | interruptDelay :: InterruptibleDelay -> IO () | ||
36 | interruptDelay d = do | ||
37 | mthread <- do | ||
38 | tryTakeMVar (delayThread d) | ||
39 | flip (maybe $ return ()) mthread $ \thread -> do | ||
40 | throwTo thread (ErrorCall "Interrupted delay") | ||
41 | |||