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
  IORef Bool
ref <- forall a. a -> IO (IORef a)
newIORef Bool
False
  forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (forall a. IO a -> IO (Async a)
async forall a b. (a -> b) -> a -> b
$ Seconds -> IORef Bool -> IO ()
worker Seconds
delay IORef Bool
ref) forall a. Async a -> IO ()
cancel forall a b. (a -> b) -> a -> b
$ \Async ()
_ -> do
    IO Bool -> IO a
action forall a b. (a -> b) -> a -> b
$ 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
  forall (f :: * -> *) a b. Applicative f => f a -> f b
forever forall a b. (a -> b) -> a -> b
$ do
    Seconds -> IO ()
sleep Seconds
delay
    forall a. IORef a -> a -> IO ()
atomicWriteIORef IORef Bool
ref Bool
True