summaryrefslogtreecommitdiff
path: root/InterruptibleDelay.hs
blob: d59ec8efba911b3c1079ebd8ab6f19d5bf171125 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
module InterruptibleDelay where

import Control.Concurrent
import Control.Monad
import Control.Exception ({-evaluate,-}handle,ErrorCall(..))
import Data.Time.Clock (NominalDiffTime)

type Microseconds = Int

microseconds :: NominalDiffTime -> Microseconds
microseconds d = round $ 1000000 * d

data InterruptibleDelay = InterruptibleDelay
        { delayThread :: MVar ThreadId
        }

interruptibleDelay :: IO InterruptibleDelay
interruptibleDelay = do
    fmap InterruptibleDelay newEmptyMVar

startDelay :: InterruptibleDelay -> Microseconds -> IO Bool
startDelay d interval = do
    thread <- myThreadId
    handle (\(ErrorCall _)-> do
                debugNoise $ "delay interrupted"
                return False) $ do 
        putMVar (delayThread d) thread
        threadDelay interval
        void $ takeMVar (delayThread d)
        return True

  where debugNoise str = return ()


interruptDelay :: InterruptibleDelay -> IO ()
interruptDelay d = do
    mthread <- do
        tryTakeMVar (delayThread d)
    flip (maybe $ return ()) mthread $ \thread -> do
    throwTo thread (ErrorCall "Interrupted delay")