-- GENERATED by C->Haskell Compiler, version 0.28.1 Switcheroo, 1 April 2016 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/Foreign/CUDA/Driver/Stream.chs" #-}
{-# LANGUAGE BangPatterns             #-}
{-# LANGUAGE EmptyDataDecls           #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TemplateHaskell          #-}
--------------------------------------------------------------------------------
-- |
-- Module    : Foreign.CUDA.Driver.Stream
-- Copyright : [2009..2014] Trevor L. McDonell
-- License   : BSD
--
-- Stream management for low-level driver interface
--
--------------------------------------------------------------------------------

module Foreign.CUDA.Driver.Stream (

  -- * Stream Management
  Stream(..), StreamFlag,
  create, createWithPriority, destroy, finished, block, getPriority,

  defaultStream,

) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Ptr as C2HSImp





{-# LINE 26 "src/Foreign/CUDA/Driver/Stream.chs" #-}


-- Friends
import Foreign.CUDA.Types
import Foreign.CUDA.Driver.Error
import Foreign.CUDA.Internal.C2HS

-- System
import Foreign
import Foreign.C
import Control.Monad                                    ( liftM )
import Control.Exception                                ( throwIO )


--------------------------------------------------------------------------------
-- Stream management
--------------------------------------------------------------------------------

-- |
-- Create a new stream.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1ga581f0c5833e21ded8b5a56594e243f4>
--
{-# INLINEABLE create #-}
create :: [StreamFlag] -> IO Stream
create !flags = resultIfOk =<< cuStreamCreate flags

{-# INLINE cuStreamCreate #-}
cuStreamCreate :: ([StreamFlag]) -> IO ((Status), (Stream))
cuStreamCreate a2 =
  alloca $ \a1' -> 
  let {a2' = combineBitMasks a2} in 
  cuStreamCreate'_ a1' a2' >>= \res ->
  let {res' = cToEnum res} in
  peekStream  a1'>>= \a1'' -> 
  return (res', a1'')

{-# LINE 56 "src/Foreign/CUDA/Driver/Stream.chs" #-}

  where
    peekStream = liftM Stream . peek


-- |
-- Create a stream with the given priority. Work submitted to
-- a higher-priority stream may preempt work already executing in a lower
-- priority stream.
--
-- The convention is that lower numbers represent higher priorities. The
-- default priority is zero. The range of meaningful numeric priorities can
-- be queried using 'Foreign.CUDA.Driver.Context.Config.getStreamPriorityRange'.
-- If the specified priority is outside the supported numerical range, it
-- will automatically be clamped to the highest or lowest number in the
-- range.
--
-- Requires CUDA-5.5.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1g95c1a8c7c3dacb13091692dd9c7f7471>
--
{-# INLINEABLE createWithPriority #-}
createWithPriority :: StreamPriority -> [StreamFlag] -> IO Stream
createWithPriority !priority !flags = resultIfOk =<< cuStreamCreateWithPriority flags priority

{-# INLINE cuStreamCreateWithPriority #-}
cuStreamCreateWithPriority :: ([StreamFlag]) -> (StreamPriority) -> IO ((Status), (Stream))
cuStreamCreateWithPriority a2 a3 =
  alloca $ \a1' -> 
  let {a2' = combineBitMasks a2} in 
  let {a3' = cIntConv a3} in 
  cuStreamCreateWithPriority'_ a1' a2' a3' >>= \res ->
  let {res' = cToEnum res} in
  peekStream  a1'>>= \a1'' -> 
  return (res', a1'')

{-# LINE 90 "src/Foreign/CUDA/Driver/Stream.chs" #-}

  where
    peekStream = liftM Stream . peek


-- |
-- Destroy a stream. If the device is still doing work in the stream when
-- 'destroy' is called, the function returns immediately and the resources
-- associated with the stream will be released automatically once the
-- device has completed all work.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1g244c8833de4596bcd31a06cdf21ee758>
--
{-# INLINEABLE destroy #-}
destroy :: Stream -> IO ()
destroy !st = nothingIfOk =<< cuStreamDestroy st

{-# INLINE cuStreamDestroy #-}
cuStreamDestroy :: (Stream) -> IO ((Status))
cuStreamDestroy a1 =
  let {a1' = useStream a1} in 
  cuStreamDestroy'_ a1' >>= \res ->
  let {res' = cToEnum res} in
  return (res')

{-# LINE 110 "src/Foreign/CUDA/Driver/Stream.chs" #-}



-- |
-- Check if all operations in the stream have completed.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1g1b0d24bbe97fa68e4bc511fb6adfeb0b>
--
{-# INLINEABLE finished #-}
finished :: Stream -> IO Bool
finished !st =
  cuStreamQuery st >>= \rv ->
  case rv of
    Success  -> return True
    NotReady -> return False
    _        -> throwIO (ExitCode rv)

{-# INLINE cuStreamQuery #-}
cuStreamQuery :: (Stream) -> IO ((Status))
cuStreamQuery a1 =
  let {a1' = useStream a1} in 
  cuStreamQuery'_ a1' >>= \res ->
  let {res' = cToEnum res} in
  return (res')

{-# LINE 129 "src/Foreign/CUDA/Driver/Stream.chs" #-}



-- |
-- Wait until the device has completed all operations in the Stream.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1g15e49dd91ec15991eb7c0a741beb7dad>
--
{-# INLINEABLE block #-}
block :: Stream -> IO ()
block !st = nothingIfOk =<< cuStreamSynchronize st

{-# INLINE cuStreamSynchronize #-}
cuStreamSynchronize :: (Stream) -> IO ((Status))
cuStreamSynchronize a1 =
  let {a1' = useStream a1} in 
  cuStreamSynchronize'_ a1' >>= \res ->
  let {res' = cToEnum res} in
  return (res')

{-# LINE 143 "src/Foreign/CUDA/Driver/Stream.chs" #-}



-- |
-- Query the priority of a stream.
--
-- Requires CUDA-5.5.
--
-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__STREAM.html#group__CUDA__STREAM_1g5bd5cb26915a2ecf1921807339488484>
--
{-# INLINEABLE getPriority #-}
getPriority :: Stream -> IO StreamPriority
getPriority !st = resultIfOk =<< cuStreamGetPriority st

{-# INLINE cuStreamGetPriority #-}
cuStreamGetPriority :: (Stream) -> IO ((Status), (StreamPriority))
cuStreamGetPriority a1 =
  let {a1' = useStream a1} in 
  alloca $ \a2' -> 
  cuStreamGetPriority'_ a1' a2' >>= \res ->
  let {res' = cToEnum res} in
  peekIntConv  a2'>>= \a2'' -> 
  return (res', a2'')

{-# LINE 166 "src/Foreign/CUDA/Driver/Stream.chs" #-}



foreign import ccall unsafe "Foreign/CUDA/Driver/Stream.chs.h cuStreamCreate"
  cuStreamCreate'_ :: ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (C2HSImp.CUInt -> (IO C2HSImp.CInt)))

foreign import ccall unsafe "Foreign/CUDA/Driver/Stream.chs.h cuStreamCreateWithPriority"
  cuStreamCreateWithPriority'_ :: ((C2HSImp.Ptr (C2HSImp.Ptr ())) -> (C2HSImp.CUInt -> (C2HSImp.CInt -> (IO C2HSImp.CInt))))

foreign import ccall unsafe "Foreign/CUDA/Driver/Stream.chs.h cuStreamDestroy"
  cuStreamDestroy'_ :: ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Foreign/CUDA/Driver/Stream.chs.h cuStreamQuery"
  cuStreamQuery'_ :: ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))

foreign import ccall safe "Foreign/CUDA/Driver/Stream.chs.h cuStreamSynchronize"
  cuStreamSynchronize'_ :: ((C2HSImp.Ptr ()) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Foreign/CUDA/Driver/Stream.chs.h cuStreamGetPriority"
  cuStreamGetPriority'_ :: ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr C2HSImp.CInt) -> (IO C2HSImp.CInt)))