{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE StrictData #-}
module System.TimeManager.Internal where
import Control.Concurrent.MVar (MVar, modifyMVar, newMVar)
import Data.IORef (IORef, readIORef)
import Data.Word (Word64)
#if defined(mingw32_HOST_OS)
import qualified System.TimeManager.Windows as EV
#else
import qualified GHC.Event as EV
#endif
newtype Manager = Manager Int
isNoManager :: Manager -> Bool
isNoManager :: Manager -> Bool
isNoManager (Manager Int
0) = Bool
True
isNoManager Manager
_ = Bool
False
type TimeoutAction = IO ()
data Handle = Handle
{ Handle -> Int
handleTimeout :: Int
, Handle -> TimeoutAction
handleAction :: TimeoutAction
, Handle -> TimerManager
handleTimerManager :: ~TimerManager
, Handle -> Lock
handleLock :: Lock
, Handle -> IORef HandleState
handleState :: ~(IORef HandleState)
, Handle -> IORef Word64
handleLastRenewed :: ~(IORef Word64)
, Handle -> Word64
handleMinRenewGap :: Word64
}
withTimeoutKey :: Handle -> (EV.TimeoutKey -> IO ()) -> IO ()
withTimeoutKey :: Handle -> (TimeoutKey -> TimeoutAction) -> TimeoutAction
withTimeoutKey Handle
h TimeoutKey -> TimeoutAction
keyF = do
HandleState
st <- IORef HandleState -> IO HandleState
forall a. IORef a -> IO a
readIORef (IORef HandleState -> IO HandleState)
-> IORef HandleState -> IO HandleState
forall a b. (a -> b) -> a -> b
$ Handle -> IORef HandleState
handleState Handle
h
case HandleState
st of
Paused TimeoutKey
key -> TimeoutKey -> TimeoutAction
keyF TimeoutKey
key
Active TimeoutKey
key -> TimeoutKey -> TimeoutAction
keyF TimeoutKey
key
HandleState
_ -> () -> TimeoutAction
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
withActiveTimeoutKey :: Handle -> (EV.TimeoutKey -> IO ()) -> IO ()
withActiveTimeoutKey :: Handle -> (TimeoutKey -> TimeoutAction) -> TimeoutAction
withActiveTimeoutKey Handle
h TimeoutKey -> TimeoutAction
keyF = do
HandleState
st <- IORef HandleState -> IO HandleState
forall a. IORef a -> IO a
readIORef (IORef HandleState -> IO HandleState)
-> IORef HandleState -> IO HandleState
forall a b. (a -> b) -> a -> b
$ Handle -> IORef HandleState
handleState Handle
h
case HandleState
st of
Active TimeoutKey
key -> TimeoutKey -> TimeoutAction
keyF TimeoutKey
key
HandleState
_ -> () -> TimeoutAction
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
type Lock = MVar ()
newLock :: IO Lock
newLock :: IO Lock
newLock = () -> IO Lock
forall a. a -> IO (MVar a)
newMVar ()
withLock :: Lock -> IO a -> IO a
withLock :: forall a. Lock -> IO a -> IO a
withLock Lock
lock IO a
action =
Lock -> (() -> IO ((), a)) -> IO a
forall a b. MVar a -> (a -> IO (a, b)) -> IO b
modifyMVar Lock
lock ((() -> IO ((), a)) -> IO a) -> (() -> IO ((), a)) -> IO a
forall a b. (a -> b) -> a -> b
$ \()
l -> do
a
a <- IO a
action
((), a) -> IO ((), a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (()
l, a
a)
data HandleState
=
Active EV.TimeoutKey
|
Paused EV.TimeoutKey
|
Stopped
|
Terminated
isEmptyHandle :: Handle -> Bool
isEmptyHandle :: Handle -> Bool
isEmptyHandle Handle{Int
TimeoutAction
Word64
Lock
IORef Word64
IORef HandleState
TimerManager
handleTimeout :: Handle -> Int
handleAction :: Handle -> TimeoutAction
handleTimerManager :: Handle -> TimerManager
handleLock :: Handle -> Lock
handleState :: Handle -> IORef HandleState
handleLastRenewed :: Handle -> IORef Word64
handleMinRenewGap :: Handle -> Word64
handleTimeout :: Int
handleAction :: TimeoutAction
handleTimerManager :: TimerManager
handleLock :: Lock
handleState :: IORef HandleState
handleLastRenewed :: IORef Word64
handleMinRenewGap :: Word64
..} = 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)
type TimerManager = EV.Manager
getTimerManager :: IO TimerManager
getTimerManager = EV.getSystemManager
#else
type TimerManager = EV.TimerManager
getTimerManager :: IO TimerManager
getTimerManager :: IO TimerManager
getTimerManager = IO TimerManager
EV.getSystemTimerManager
#endif