packages feed

clock-0.1: System/CPUTime/Clock.hs

module System.CPUTime.Clock (

  Clock (Monotonic, Realtime, ProcessTime, ThreadTime),
  TimeSpec (Time),

  clock_gettime,
  clock_getres,

  sec,
  nsec,  

) where

import GHC.Ptr
--import System.IO.Unsafe
import Foreign.Storable
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array

-- Reader function
type ReaderFunc = Ptr Int → IO ()

-- Readers
-- | 
foreign import ccall clock_readtime_monotonic :: ReaderFunc
foreign import ccall clock_readtime_realtime :: ReaderFunc
foreign import ccall clock_readtime_processtime :: ReaderFunc
foreign import ccall clock_readtime_threadtime :: ReaderFunc

foreign import ccall clock_readres_monotonic :: ReaderFunc
foreign import ccall clock_readres_realtime :: ReaderFunc
foreign import ccall clock_readres_processtime :: ReaderFunc
foreign import ccall clock_readres_threadtime :: ReaderFunc


-- Clock types
data Clock = Monotonic | Realtime | ProcessTime | ThreadTime

-- Clock-to-time reading
time :: Clock → ReaderFunc
time Monotonic = clock_readtime_monotonic
time Realtime  = clock_readtime_realtime
time ProcessTime = clock_readtime_processtime
time ThreadTime = clock_readtime_threadtime

-- Clock-to-res reading
res :: Clock → ReaderFunc
res Monotonic = clock_readres_monotonic
res Realtime  = clock_readres_realtime
res ProcessTime = clock_readres_processtime
res ThreadTime = clock_readres_threadtime

-- TimeSpec structure
data TimeSpec = Time Int Int deriving (Show, Read)
sec  :: TimeSpec → Int
nsec :: TimeSpec → Int
sec  (Time s _) = s
nsec (Time _ n) = n

-- clock_gettime
clock_gettime :: Clock → IO TimeSpec
clock_gettime = call . time

-- clock_getres
clock_getres :: Clock → IO TimeSpec
clock_getres = call . res

-- core function
call :: ReaderFunc → IO TimeSpec
call read_ = do
  t ← (2 ↑≣)
  read_ t
  s ← (t ≣→ 0)
  n ← (t ≣→ 1)
  (t ≣⊠)
  return $ Time s n

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

(↑≣) :: Storable a ⇒ Int → IO (Ptr a)
(↑≣) = mallocArray

(≣→) :: Storable a ⇒ Ptr a → Int → IO a
(≣→) = peekElemOff

(≣⊠) :: Ptr a → IO ()
(≣⊠) = Foreign.Marshal.Alloc.free