{-# LINE 1 "System/Posix/Realtime/Aio.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
{-# LINE 2 "System/Posix/Realtime/Aio.hsc" #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  System.Posix.Realtime.Aio
-- 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 1003.1b  POSIX Asynchronous I/O 
--
-----------------------------------------------------------------------------

module System.Posix.Realtime.Aio (

   AIOCB,

   makeAIOCB,           --  Fd -> Int -> Int -> FileOffset -> Ptr Word8 -> ByteCount -> Sigevent -> IO (AIOCB)

   aioRead,             --  AIOCB -> IO ()  

   aioWrite,            --  AIOCB -> IO ()

   aioReturn,           --  AIOCB -> IO (ByteCount)

   aioError,            --  AIOCB -> IO (Errno)

   aioCancel,           --  Fd -> AIOCB -> IO ()

   SyncOp(..),

   aioFsync,            --  SyncOp -> AIOCB -> IO ()

   aioSuspend,          --  [AIOCB] -> TimeSpec -> IO ()

   ListIOMode,

   lioListIO,           --  ListIOMode -> [AIOCB] -> Sigevent -> IO ()


  ) where



import System.IO
import System.IO.Error
import System.Posix.Realtime.RTDataTypes
import System.Posix.Types
import System.Posix.Error
import System.Posix.Internals

import Foreign
import Foreign.C
import Data.Bits



{-# LINE 60 "System/Posix/Realtime/Aio.hsc" #-}
import GHC.IO
import GHC.IO.Handle hiding (fdToHandle)
import qualified GHC.IO.Handle

{-# LINE 64 "System/Posix/Realtime/Aio.hsc" #-}


{-# LINE 69 "System/Posix/Realtime/Aio.hsc" #-}


{-# LINE 71 "System/Posix/Realtime/Aio.hsc" #-}

{-# LINE 72 "System/Posix/Realtime/Aio.hsc" #-}

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




data AIOCBStruct

type AIOCB = ForeignPtr AIOCBStruct


-- | Posix AIO return
aioRead :: AIOCB -> IO ()  
aioRead p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      throwErrnoIfMinus1 "aioRead" (c_aio_read  p_aiocb)  
      return ()

foreign import ccall safe "aio.h aio_read"
    c_aio_read :: Ptr AIOCBStruct -> IO CInt



-- | Posix AIO write
aioWrite :: AIOCB -> IO ()
aioWrite p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      throwErrnoIfMinus1 "aioWrite" (c_aio_write  p_aiocb)  
      return ()

foreign import ccall safe "aio.h aio_write"
    c_aio_write :: Ptr AIOCBStruct -> IO CInt



-- | Posix AIO return
aioReturn :: AIOCB -> IO (ByteCount)
aioReturn p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      count <- (c_aio_return  p_aiocb)  
      return (fromIntegral count)

foreign import ccall safe "aio.h aio_return"
    c_aio_return :: Ptr AIOCBStruct -> IO CInt



-- | Posix AIO error
aioError :: AIOCB -> IO (Errno)
aioError p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      errno <- (c_aio_error  p_aiocb)  
      return (Errno errno)

foreign import ccall safe "aio.h aio_error"
    c_aio_error :: Ptr AIOCBStruct -> IO CInt 



-- | Posix AIO cancel
aioCancel :: Fd -> AIOCB -> IO ()
aioCancel (Fd fd) p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      throwErrnoIfMinus1 "aioCancel" (c_aio_cancel fd p_aiocb)  
      return ()

foreign import ccall safe "aio.h aio_cancel"
    c_aio_cancel :: CInt -> Ptr AIOCBStruct -> IO CInt




-- | Posix asynchronous file synchronization!
data SyncOp = DSync | Sync
aioFsync :: SyncOp -> AIOCB -> IO ()
aioFsync DSync p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      throwErrnoIfMinus1 "aioFsync" (c_aio_fsync (4096) p_aiocb)  
{-# LINE 150 "System/Posix/Realtime/Aio.hsc" #-}
      return ()
aioFsync Sync p_aiocb = do
   withForeignPtr p_aiocb $ \ p_aiocb -> do
      throwErrnoIfMinus1 "aioFsync" (c_aio_fsync (1052672) p_aiocb)  
{-# LINE 154 "System/Posix/Realtime/Aio.hsc" #-}
      return ()

foreign import ccall safe "aio.h aio_fsync"
    c_aio_fsync :: CInt -> Ptr AIOCBStruct -> IO CInt




-- | Posix AIO lio_listio
type ListIOMode = Int -- <<< need to have mapping from Haskell datatype->Int?
lioListIO :: ListIOMode -> [AIOCB] -> Sigevent -> IO ()
lioListIO mode [] sigEvent = do
    return ()
lioListIO mode aiocbs sigEvent = do
    let numAiocbs = length aiocbs
    p_aiocbs <- mapM foreignPtrToPtr aiocbs
    p_p_aiocbs <- newArray p_aiocbs
    allocaBytes (64) $ \ p_sigevent -> do
{-# LINE 172 "System/Posix/Realtime/Aio.hsc" #-}
       poke p_sigevent sigEvent
       throwErrnoIfMinus1 "lioListIO" (c_lio_listio (fromIntegral mode) p_p_aiocbs (fromIntegral numAiocbs) p_sigevent)
       return ()
     
foreign import ccall safe "aio.h lio_listio"
    c_lio_listio :: CInt -> Ptr (Ptr AIOCBStruct) -> CInt -> Ptr Sigevent -> IO CInt



-- | Posix AIO suspend
aioSuspend :: [AIOCB] -> TimeSpec -> IO ()
aioSuspend [] timeSpec = do
   return ()
aioSuspend aiocbs timeSpec = do
    let numAiocbs = length aiocbs
    p_aiocbs <- mapM foreignPtrToPtr aiocbs
    p_p_aiocbs <- newArray p_aiocbs
    allocaBytes (16) $ \ p_timespec -> do
{-# LINE 190 "System/Posix/Realtime/Aio.hsc" #-}
       poke p_timespec timeSpec
       throwErrnoIfMinus1 "aioSuspend" (c_aio_suspend p_p_aiocbs (fromIntegral numAiocbs) p_timespec)
       return ()

foreign import ccall safe "aio.h aio_suspend"
    c_aio_suspend :: Ptr (Ptr AIOCBStruct) -> CInt -> Ptr TimeSpec -> IO CInt




-- | makeAIOCB is a helper function that builds an "aiocb" from all its fields
makeAIOCB :: Fd -> Int -> Int -> FileOffset -> Ptr Word8 -> ByteCount -> Sigevent -> IO (AIOCB)
makeAIOCB fd lioOpcode reqPrio fileOffset buffer byteCount sigEvent = do

   fptr <- mallocForeignPtrBytes (168)
{-# LINE 205 "System/Posix/Realtime/Aio.hsc" #-}

   withForeignPtr fptr $ \ptr -> do
      
       ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr fd
{-# LINE 209 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) ptr lioOpcode
{-# LINE 211 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) ptr reqPrio
{-# LINE 213 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 128)) ptr fileOffset
{-# LINE 215 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) ptr buffer 
{-# LINE 217 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 24)) ptr byteCount
{-# LINE 219 "System/Posix/Realtime/Aio.hsc" #-}

       ((\hsc_ptr -> pokeByteOff hsc_ptr 32)) ptr sigEvent
{-# LINE 221 "System/Posix/Realtime/Aio.hsc" #-}

       return (fptr)




foreignPtrToPtr :: ForeignPtr AIOCBStruct -> IO (Ptr AIOCBStruct)
foreignPtrToPtr  fptr = do
   withForeignPtr fptr $ \ptr -> do
      return (ptr)