{-# OPTIONS_GHC -optc-DHS_CLOCK_HAVE_PROCESS_CPUTIME #-}
{-# OPTIONS_GHC -optc-DHS_CLOCK_HAVE_THREAD_CPUTIME #-}
{-# LINE 1 "System/Clock.hsc" #-}
{-# LANGUAGE CApiFFI #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module System.Clock
( Clock(..)
, TimeSpec(..)
, getTime
, getRes
, fromNanoSecs
, toNanoSecs
, diffTimeSpec
, timeSpecAsNanoSecs
, normalize
, s2ns
) where
import Control.Applicative ((<$>), (<*>))
import Data.Int
import Data.Word
import Data.Ratio
import Data.Typeable (Typeable)
import Foreign.C
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal.Alloc
import GHC.Generics (Generic)
{-# LINE 41 "System/Clock.hsc" #-}
{-# LINE 43 "System/Clock.hsc" #-}
{-# LINE 45 "System/Clock.hsc" #-}
{-# LINE 46 "System/Clock.hsc" #-}
{-# LINE 48 "System/Clock.hsc" #-}
import System.Posix.Types
{-# LINE 50 "System/Clock.hsc" #-}
{-# LINE 54 "System/Clock.hsc" #-}
data Clock
= Monotonic
| Realtime
{-# LINE 82 "System/Clock.hsc" #-}
| ProcessCPUTime
{-# LINE 87 "System/Clock.hsc" #-}
{-# LINE 89 "System/Clock.hsc" #-}
| ThreadCPUTime
{-# LINE 94 "System/Clock.hsc" #-}
{-# LINE 96 "System/Clock.hsc" #-}
| MonotonicRaw
{-# LINE 104 "System/Clock.hsc" #-}
{-# LINE 106 "System/Clock.hsc" #-}
| Boottime
{-# LINE 117 "System/Clock.hsc" #-}
{-# LINE 119 "System/Clock.hsc" #-}
| MonotonicCoarse
{-# LINE 125 "System/Clock.hsc" #-}
{-# LINE 127 "System/Clock.hsc" #-}
| RealtimeCoarse
{-# LINE 133 "System/Clock.hsc" #-}
deriving (Eq, Enum, Generic, Read, Show, Typeable)
{-# LINE 146 "System/Clock.hsc" #-}
{-# LINE 147 "System/Clock.hsc" #-}
type ClockId = CClockId
{-# LINE 151 "System/Clock.hsc" #-}
foreign import ccall unsafe clock_gettime :: ClockId -> Ptr TimeSpec -> IO CInt
foreign import ccall unsafe clock_getres :: ClockId -> Ptr TimeSpec -> IO CInt
foreign import capi unsafe "time.h value CLOCK_MONOTONIC" clock_MONOTONIC :: ClockId
foreign import capi unsafe "time.h value CLOCK_REALTIME" clock_REALTIME :: ClockId
{-# LINE 158 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_PROCESS_CPUTIME_ID" clock_PROCESS_CPUTIME_ID :: ClockId
{-# LINE 160 "System/Clock.hsc" #-}
{-# LINE 161 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_THREAD_CPUTIME_ID" clock_THREAD_CPUTIME_ID :: ClockId
{-# LINE 163 "System/Clock.hsc" #-}
{-# LINE 164 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_MONOTONIC_RAW" clock_MONOTONIC_RAW :: ClockId
{-# LINE 166 "System/Clock.hsc" #-}
{-# LINE 167 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_BOOTTIME" clock_BOOTTIME :: ClockId
{-# LINE 169 "System/Clock.hsc" #-}
{-# LINE 170 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_MONOTONIC_COARSE" clock_MONOTONIC_COARSE :: ClockId
{-# LINE 172 "System/Clock.hsc" #-}
{-# LINE 173 "System/Clock.hsc" #-}
foreign import capi unsafe "time.h value CLOCK_REALTIME_COARSE" clock_REALTIME_COARSE :: ClockId
{-# LINE 175 "System/Clock.hsc" #-}
{-# LINE 176 "System/Clock.hsc" #-}
{-# LINE 178 "System/Clock.hsc" #-}
clockToConst :: Clock -> ClockId
clockToConst Monotonic = clock_MONOTONIC
clockToConst Realtime = clock_REALTIME
{-# LINE 182 "System/Clock.hsc" #-}
clockToConst ProcessCPUTime = clock_PROCESS_CPUTIME_ID
{-# LINE 184 "System/Clock.hsc" #-}
{-# LINE 185 "System/Clock.hsc" #-}
clockToConst ThreadCPUTime = clock_THREAD_CPUTIME_ID
{-# LINE 187 "System/Clock.hsc" #-}
{-# LINE 188 "System/Clock.hsc" #-}
clockToConst MonotonicRaw = clock_MONOTONIC_RAW
{-# LINE 190 "System/Clock.hsc" #-}
{-# LINE 191 "System/Clock.hsc" #-}
clockToConst Boottime = clock_BOOTTIME
{-# LINE 193 "System/Clock.hsc" #-}
{-# LINE 194 "System/Clock.hsc" #-}
clockToConst MonotonicCoarse = clock_MONOTONIC_COARSE
{-# LINE 196 "System/Clock.hsc" #-}
{-# LINE 197 "System/Clock.hsc" #-}
clockToConst RealtimeCoarse = clock_REALTIME_COARSE
{-# LINE 199 "System/Clock.hsc" #-}
{-# LINE 200 "System/Clock.hsc" #-}
allocaAndPeek :: Storable a => (Ptr a -> IO ()) -> IO a
allocaAndPeek f = alloca $ \ptr -> f ptr >> peek ptr
getTime :: Clock -> IO TimeSpec
getRes :: Clock -> IO TimeSpec
{-# LINE 219 "System/Clock.hsc" #-}
getTime clk = allocaAndPeek $! throwErrnoIfMinus1_ "clock_gettime" . clock_gettime (clockToConst clk)
{-# LINE 221 "System/Clock.hsc" #-}
{-# LINE 228 "System/Clock.hsc" #-}
getRes clk = allocaAndPeek $! throwErrnoIfMinus1_ "clock_getres" . clock_getres (clockToConst clk)
{-# LINE 230 "System/Clock.hsc" #-}
data TimeSpec = TimeSpec
{ sec :: {-# UNPACK #-} !Int64
, nsec :: {-# UNPACK #-} !Int64
} deriving (Generic, Read, Show, Typeable)
{-# LINE 249 "System/Clock.hsc" #-}
instance Storable TimeSpec where
sizeOf _ = (16)
{-# LINE 251 "System/Clock.hsc" #-}
alignment _ = 8
{-# LINE 252 "System/Clock.hsc" #-}
poke ptr ts = do
let xs :: Int64 = fromIntegral $ sec ts
{-# LINE 254 "System/Clock.hsc" #-}
xn :: Int64 = fromIntegral $ nsec ts
{-# LINE 255 "System/Clock.hsc" #-}
(\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr (xs)
{-# LINE 256 "System/Clock.hsc" #-}
(\hsc_ptr -> pokeByteOff hsc_ptr 8) ptr (xn)
{-# LINE 257 "System/Clock.hsc" #-}
peek ptr = do
xs :: Int64 <- (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 259 "System/Clock.hsc" #-}
xn :: Int64 <- (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 260 "System/Clock.hsc" #-}
return $ TimeSpec (fromIntegral xs) (fromIntegral xn)
{-# LINE 262 "System/Clock.hsc" #-}
s2ns :: Num a => a
s2ns = 10^9
normalize :: TimeSpec -> TimeSpec
normalize (TimeSpec xs xn) | xn < 0 || xn >= s2ns = TimeSpec (xs + q) r
| otherwise = TimeSpec xs xn
where (q, r) = xn `divMod` s2ns
instance Num TimeSpec where
(TimeSpec xs xn) + (TimeSpec ys yn) = normalize $! TimeSpec (xs + ys) (xn + yn)
(TimeSpec xs xn) - (TimeSpec ys yn) = normalize $! TimeSpec (xs - ys) (xn - yn)
(normalize -> TimeSpec xs xn) * (normalize -> TimeSpec ys yn) = normalize $! TimeSpec (s2ns*xs*ys+xs*yn+xn*ys) (xn*yn)
negate (TimeSpec xs xn) = normalize $! TimeSpec (negate xs) (negate xn)
abs (normalize -> TimeSpec xs xn) | xs == 0 = normalize $! TimeSpec 0 xn
| otherwise = normalize $! TimeSpec (abs xs) (signum xs * xn)
signum (normalize -> TimeSpec xs xn) | xs == 0 = TimeSpec 0 (signum xn)
| otherwise = TimeSpec 0 (signum xs)
fromInteger x = TimeSpec (fromInteger q) (fromInteger r) where (q, r) = x `divMod` s2ns
instance Enum TimeSpec where
succ x = x + 1
pred x = x - 1
toEnum x = normalize $ TimeSpec 0 (fromIntegral x)
fromEnum = fromEnum . toInteger
instance Real TimeSpec where
toRational x = toInteger x % 1
instance Integral TimeSpec where
toInteger = toNanoSecs
quot (toInteger-> t1) (toInteger-> t2) = fromInteger $! quot t1 t2
rem (toInteger-> t1) (toInteger-> t2) = fromInteger $! rem t1 t2
div (toInteger-> t1) (toInteger-> t2) = fromInteger $! div t1 t2
mod (toInteger-> t1) (toInteger-> t2) = fromInteger $! mod t1 t2
divMod (toInteger-> t1) (toInteger-> t2) =
let (q,r)=divMod t1 t2 in (fromInteger $! q, fromInteger $! r)
quotRem (toInteger-> t1) (toInteger-> t2) =
let (q,r)=quotRem t1 t2 in (fromInteger $! q, fromInteger $! r)
instance Eq TimeSpec where
(normalize -> TimeSpec xs xn) == (normalize -> TimeSpec ys yn) | True == es = xn == yn
| otherwise = es
where es = xs == ys
instance Ord TimeSpec where
compare (normalize -> TimeSpec xs xn) (normalize -> TimeSpec ys yn) | EQ == os = compare xn yn
| otherwise = os
where os = compare xs ys
instance Bounded TimeSpec where
minBound = TimeSpec minBound 0
maxBound = TimeSpec maxBound (s2ns-1)
fromNanoSecs :: Integer -> TimeSpec
fromNanoSecs x = TimeSpec (fromInteger q) (fromInteger r) where (q, r) = x `divMod` s2ns
toNanoSecs :: TimeSpec -> Integer
toNanoSecs (TimeSpec (toInteger -> s) (toInteger -> n)) = s * s2ns + n
diffTimeSpec :: TimeSpec -> TimeSpec -> TimeSpec
diffTimeSpec ts1 ts2 = abs (ts1 - ts2)
{-# DEPRECATED timeSpecAsNanoSecs "Use toNanoSecs instead! Replaced timeSpecAsNanoSecs with the same signature TimeSpec -> Integer" #-}
timeSpecAsNanoSecs :: TimeSpec -> Integer
timeSpecAsNanoSecs (TimeSpec s n) = toInteger s * s2ns + toInteger n