{-# LANGUAGE CPP #-}
module Foundation.Time.Bindings
    ( measuringNanoSeconds
    , getMonotonicTime
    ) where

import Basement.Imports
import Basement.Types.OffsetSize
import Basement.Types.Ptr
import Foundation.System.Bindings.Time
import Foundation.Time.Types
import Foundation.Foreign.Alloc
import Foreign.Storable

measuringNanoSeconds :: IO a -> IO (a, NanoSeconds)
measuringNanoSeconds :: IO a -> IO (a, NanoSeconds)
measuringNanoSeconds IO a
f =
    CountOf Word8
-> (Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds)
forall a b. CountOf Word8 -> (Ptr a -> IO b) -> IO b
allocaBytes (CSize -> CountOf Word8
sizeOfCSize CSize
size_CTimeSpec) ((Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds))
-> (Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds)
forall a b. (a -> b) -> a -> b
$ \Ptr CTimeSpec
t1 ->
    CountOf Word8
-> (Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds)
forall a b. CountOf Word8 -> (Ptr a -> IO b) -> IO b
allocaBytes (CSize -> CountOf Word8
sizeOfCSize CSize
size_CTimeSpec) ((Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds))
-> (Ptr CTimeSpec -> IO (a, NanoSeconds)) -> IO (a, NanoSeconds)
forall a b. (a -> b) -> a -> b
$ \Ptr CTimeSpec
t2 -> do
        CInt
_err1 <- CInt -> Ptr CTimeSpec -> IO CInt
sysTimeClockGetTime CInt
sysTime_CLOCK_MONOTONIC Ptr CTimeSpec
t1
        a
r <- IO a
f
        CInt
_err2 <- CInt -> Ptr CTimeSpec -> IO CInt
sysTimeClockGetTime CInt
sysTime_CLOCK_MONOTONIC Ptr CTimeSpec
t2
        (a, NanoSeconds) -> IO (a, NanoSeconds)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
r, Word64 -> NanoSeconds
NanoSeconds Word64
0)

getMonotonicTime :: IO (Seconds, NanoSeconds)
getMonotonicTime :: IO (Seconds, NanoSeconds)
getMonotonicTime =
    CountOf Word8
-> (Ptr CTimeSpec -> IO (Seconds, NanoSeconds))
-> IO (Seconds, NanoSeconds)
forall a b. CountOf Word8 -> (Ptr a -> IO b) -> IO b
allocaBytes (CSize -> CountOf Word8
sizeOfCSize CSize
size_CTimeSpec) ((Ptr CTimeSpec -> IO (Seconds, NanoSeconds))
 -> IO (Seconds, NanoSeconds))
-> (Ptr CTimeSpec -> IO (Seconds, NanoSeconds))
-> IO (Seconds, NanoSeconds)
forall a b. (a -> b) -> a -> b
$ \Ptr CTimeSpec
tspec -> do
        CInt
_err1 <- CInt -> Ptr CTimeSpec -> IO CInt
sysTimeClockGetTime CInt
sysTime_CLOCK_MONOTONIC Ptr CTimeSpec
tspec
        Seconds
s  <- Word64 -> Seconds
Seconds     (Word64 -> Seconds) -> IO Word64 -> IO Seconds
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr CTimeSpec -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr (Ptr CTimeSpec
tspec Ptr CTimeSpec -> Offset Word8 -> Ptr CTimeSpec
forall a. Ptr a -> Offset Word8 -> Ptr a
`ptrPlus` Offset Word8
ofs_CTimeSpec_Seconds))
        NanoSeconds
ns <- Word64 -> NanoSeconds
NanoSeconds (Word64 -> NanoSeconds) -> IO Word64 -> IO NanoSeconds
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word64 -> IO Word64
forall a. Storable a => Ptr a -> IO a
peek (Ptr CTimeSpec -> Ptr Word64
forall a b. Ptr a -> Ptr b
castPtr (Ptr CTimeSpec
tspec Ptr CTimeSpec -> Offset Word8 -> Ptr CTimeSpec
forall a. Ptr a -> Offset Word8 -> Ptr a
`ptrPlus` Offset Word8
ofs_CTimeSpec_NanoSeconds))
        (Seconds, NanoSeconds) -> IO (Seconds, NanoSeconds)
forall (m :: * -> *) a. Monad m => a -> m a
return (Seconds
s,NanoSeconds
ns)