{-# LINE 1 "System/Posix/Realtime/RTTime.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LINE 2 "System/Posix/Realtime/RTTime.hsc" #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  System.Posix.Realtime.RTTimer
-- Copyright   :  (c) The University of Glasgow 2002
-- License     :  BSD-style (see the file libraries/base/LICENSE)
-- 
-- Maintainer  :  William N. Halchin (vigalchin@gmail.com)
-- Stability   :  provisional
-- Portability :  non-portable (requires POSIX)
--
-- POSIX Realtime Timer and Clock support
--
-----------------------------------------------------------------------------

module System.Posix.Realtime.RTTime (

   TimerId,

   ClockId(..),

   SetTimeFlag(..),


   timerCreate,                 --  ClockId -> Maybe Sigevent -> IO (TimerId)

   timerDelete,                 --  TimerId -> IO ()

   timerSetTime,                --  TimerId -> SetTimeFlag -> ItimerSpec -> IO (ItimerSpec)

   timerGetTime,                --  TimerId -> IO (ItimerSpec)

   timerGetOverrun,             --  TimerId -> IO Int


   clockGetRes,                 --  ClockId -> IO TimeSpec

   clockGetTime,                --  ClockId -> IO TimeSpec

   clockSetTime                 --  ClockId -> TimeSpec -> IO ()
   

  ) where


{-# LINE 46 "System/Posix/Realtime/RTTime.hsc" #-}

{-# LINE 47 "System/Posix/Realtime/RTTime.hsc" #-}

import System.Posix.Realtime.RTDataTypes     
import System.Posix.Types
import System.Posix.Error
import System.Posix.Internals
import Foreign
import Foreign.C

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


type TimerId = Int


data ClockId = 
    Clock_Realtime             | 
    Clock_Monotonic            |
    Clock_Process_CPUTime_ID   |
    Clock_Thread_CPUTime_ID

type CClockId = Int 


data SetTimeFlag = Timer_Abstime



-- | Create a realtime timer
timerCreate :: ClockId -> Maybe Sigevent -> IO (TimerId)
timerCreate clockId (Just sigEvent) = do
    allocaBytes (64) $ \ p_sigevent -> do
{-# LINE 79 "System/Posix/Realtime/RTTime.hsc" #-}
       allocaBytes (4) $ \ p_timerId -> do
{-# LINE 80 "System/Posix/Realtime/RTTime.hsc" #-}
          poke p_sigevent sigEvent 
          throwErrnoIfMinus1 "timerCreate" (c_timer_create (fromIntegral (mapClockId clockId)) p_sigevent p_timerId)
          timerId <- peek p_timerId
          return  (timerId) 
timerCreate clockId Nothing = do
   allocaBytes (4) $ \ p_timerId -> do
{-# LINE 86 "System/Posix/Realtime/RTTime.hsc" #-}
      throwErrnoIfMinus1 "timerCreate" (c_timer_create (fromIntegral (mapClockId clockId)) nullPtr p_timerId)
      timerId <- peek p_timerId
      return  (timerId)
      

foreign import ccall safe "time.h timer_create"
   c_timer_create :: CInt -> Ptr Sigevent -> Ptr TimerId -> IO CInt




-- | Delete the timer designated by "timerId".
timerDelete :: TimerId -> IO ()
timerDelete timerId = do
   throwErrnoIfMinus1 "timerDelete" (c_timer_delete (fromIntegral timerId))
   return ()

foreign import ccall safe "time.h timer_delete"
    c_timer_delete :: CInt -> IO CInt



-- | Get the current timer state
timerGetTime :: TimerId -> IO (ItimerSpec)
timerGetTime timerId = do 
   allocaBytes (32) $ \ p_itimerSpec -> do
{-# LINE 112 "System/Posix/Realtime/RTTime.hsc" #-}
      throwErrnoIfMinus1 "timerGettime" (c_timer_gettime (fromIntegral timerId) p_itimerSpec) 
      itimerSpec <- peek p_itimerSpec
      return (itimerSpec)

foreign import ccall safe "time.h timer_gettime"
    c_timer_gettime :: CInt -> Ptr ItimerSpec-> IO CInt 



-- | Set the current timer state
timerSetTime :: TimerId -> SetTimeFlag -> ItimerSpec -> IO (ItimerSpec)
timerSetTime timerId setTimeFlag itimerSpec = do 
   allocaBytes (32) $ \ p_itimerSpec -> do
{-# LINE 125 "System/Posix/Realtime/RTTime.hsc" #-}
      poke p_itimerSpec itimerSpec
      allocaBytes (32) $ \ p_olditimerSpec -> do
{-# LINE 127 "System/Posix/Realtime/RTTime.hsc" #-}
         throwErrnoIfMinus1 "timerSettime" (c_timer_settime (fromIntegral timerId) (cSetTimeFlag) p_itimerSpec p_olditimerSpec) 
         olditimerSpec <- peek p_olditimerSpec
         return (olditimerSpec)
  where
     cSetTimeFlag = case setTimeFlag of
        Timer_Abstime -> (1) 
{-# LINE 133 "System/Posix/Realtime/RTTime.hsc" #-}


foreign import ccall safe "time.h timer_settime"
    c_timer_settime :: CInt -> CInt -> Ptr ItimerSpec -> Ptr ItimerSpec-> IO CInt 



-- | Get the timer overrun count!
timerGetOverrun :: TimerId -> IO Int
timerGetOverrun timerId = do
   rc <- throwErrnoIfMinus1 "timerGetoverrun" (c_timer_getoverrun (fromIntegral timerId))
   return (fromIntegral rc)

foreign import ccall safe "time.h timer_getoverrun"
    c_timer_getoverrun :: CInt -> IO CInt





-- | Get clock resolution
clockGetRes :: ClockId -> IO TimeSpec
clockGetRes clockId = do
   allocaBytes (16) $ \ p_timeSpec -> do
{-# LINE 157 "System/Posix/Realtime/RTTime.hsc" #-}
      throwErrnoIfMinus1 "clockGetres" (c_clock_getres (fromIntegral (mapClockId clockId)) p_timeSpec) 
      timeSpec <- peek p_timeSpec
      return (timeSpec)
   
foreign import ccall safe "time.h clock_getres"
    c_clock_getres :: CInt -> Ptr TimeSpec -> IO CInt



-- | Get clock time
clockGetTime :: ClockId -> IO TimeSpec
clockGetTime clockId = do
   allocaBytes (16) $ \ p_timeSpec -> do
{-# LINE 170 "System/Posix/Realtime/RTTime.hsc" #-}
      throwErrnoIfMinus1 "clockGettime" (c_clock_gettime (fromIntegral (mapClockId clockId)) p_timeSpec) 
      timeSpec <- peek p_timeSpec
      return (timeSpec)
   

foreign import ccall safe "time.h clock_gettime"
    c_clock_gettime :: CInt -> Ptr TimeSpec -> IO CInt



-- | Set clock time
clockSetTime :: ClockId -> TimeSpec -> IO ()
clockSetTime clockId timeSpec = do
   allocaBytes (16) $ \ p_timeSpec -> do
{-# LINE 184 "System/Posix/Realtime/RTTime.hsc" #-}
      throwErrnoIfMinus1 "clockSettime" (c_clock_settime (fromIntegral (mapClockId clockId)) p_timeSpec) 
      return ()
   

foreign import ccall safe "time.h clock_settime"
    c_clock_settime :: CInt -> Ptr TimeSpec -> IO CInt



-- | Helper function that maps a clockid to it's C representation!
mapClockId :: ClockId -> CClockId
mapClockId clockId =
   case clockId of
      Clock_Realtime             -> (0)
{-# LINE 198 "System/Posix/Realtime/RTTime.hsc" #-}
      Clock_Monotonic            -> (1)
{-# LINE 199 "System/Posix/Realtime/RTTime.hsc" #-}
      Clock_Process_CPUTime_ID   -> (2)
{-# LINE 200 "System/Posix/Realtime/RTTime.hsc" #-}
      Clock_Thread_CPUTime_ID    -> (3)
{-# LINE 201 "System/Posix/Realtime/RTTime.hsc" #-}