module Test.Hspec.Core.Timer (withTimer) where

import           Prelude ()
import           Test.Hspec.Core.Compat

import           Control.Concurrent.Async

import           Test.Hspec.Core.Clock

withTimer :: Seconds -> (IO Bool -> IO a) -> IO a
withTimer :: forall a. Seconds -> (IO Bool -> IO a) -> IO a
withTimer Seconds
delay IO Bool -> IO a
action = do
  ref <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
  bracket (async $ worker delay ref) cancel $ \Async ()
_ -> do
    IO Bool -> IO a
action (IO Bool -> IO a) -> IO Bool -> IO a
forall a b. (a -> b) -> a -> b
$ IORef Bool -> (Bool -> (Bool, Bool)) -> IO Bool
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef Bool
ref (\Bool
a -> (Bool
False, Bool
a))

worker :: Seconds -> IORef Bool -> IO ()
worker :: Seconds -> IORef Bool -> IO ()
worker Seconds
delay IORef Bool
ref = do
  IO () -> IO ()
forall (f :: * -> *) a b. Applicative f => f a -> f b
forever (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    Seconds -> IO ()
sleep Seconds
delay
    IORef Bool -> Bool -> IO ()
forall a. IORef a -> a -> IO ()
atomicWriteIORef IORef Bool
ref Bool
True