{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}

module System.TimeManager.Internal where

import Data.IORef (IORef)

#if defined(mingw32_HOST_OS)
import qualified GHC.Event.Windows as EV
#else
import qualified GHC.Event as EV
#endif

----------------------------------------------------------------

-- | A timeout manager
newtype Manager = Manager Int

isNoManager :: Manager -> Bool
isNoManager :: Manager -> Bool
isNoManager (Manager Int
0) = Bool
True
isNoManager Manager
_ = Bool
False

----------------------------------------------------------------

-- | An action (callback) to be performed on timeout.
type TimeoutAction = IO ()

-- | A handle used by a timeout manager.
data Handle = Handle
    { Handle -> Int
handleTimeout :: Int
    , Handle -> TimeoutAction
handleAction :: TimeoutAction
    , Handle -> IORef TimeoutKey
handleKeyRef :: ~(IORef EV.TimeoutKey)
    , Handle -> IORef HandleState
handleState :: ~(IORef HandleState)
    }

-- | Tracking the state of a handle, to be able to have 'resume'
-- act like a 'register' or 'tickle'.
data HandleState = Active | Stopped

isEmptyHandle :: Handle -> Bool
isEmptyHandle :: Handle -> Bool
isEmptyHandle Handle{Int
TimeoutAction
IORef TimeoutKey
IORef HandleState
handleTimeout :: Handle -> Int
handleAction :: Handle -> TimeoutAction
handleKeyRef :: Handle -> IORef TimeoutKey
handleState :: Handle -> IORef HandleState
handleTimeout :: Int
handleAction :: TimeoutAction
handleKeyRef :: IORef TimeoutKey
handleState :: IORef HandleState
..} = Int
handleTimeout Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

withNonEmptyHandle :: Handle -> IO () -> IO ()
withNonEmptyHandle :: Handle -> TimeoutAction -> TimeoutAction
withNonEmptyHandle Handle
h TimeoutAction
act =
    if Handle -> Bool
isEmptyHandle Handle
h then () -> TimeoutAction
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure () else TimeoutAction
act

#if defined(mingw32_HOST_OS)
getTimerManager :: IO EV.Manager
getTimerManager = EV.getSystemManager
#else
getTimerManager :: IO EV.TimerManager
getTimerManager :: IO TimerManager
getTimerManager = IO TimerManager
EV.getSystemTimerManager
#endif