   CLCommandQueue -> CLKernel -> CLuint -> Ptr CSize -> Ptr CSize -> Ptr CSize -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
 foreign import ccall "clEnqueueTask" raw_clEnqueueTask :: 
   CLCommandQueue -> CLKernel -> CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint
+foreign import ccall "clEnqueueMarker" raw_clEnqueueMarker :: 
+  CLCommandQueue -> Ptr CLEvent -> IO CLint 
+foreign import ccall "clEnqueueWaitForEvents" raw_clEnqueueWaitForEvents :: 
+  CLCommandQueue -> CLuint -> Ptr CLEvent -> IO CLint
+foreign import ccall "clEnqueueBarrier" raw_clEnqueueBarrier :: 
+  CLCommandQueue -> IO CLint 
 foreign import ccall "clFlush" raw_clFlush ::
   CLCommandQueue -> IO CLint
 foreign import ccall "clFinish" raw_clFinish ::

      infoid = getCLValue CL_QUEUE_PROPERTIES
      size = fromIntegral $ sizeOf (0::CLCommandQueueProperty_)

-- | Enable or disable the properties of a command-queue.
-- Returns the command-queue properties before they were changed by 
-- 'clSetCommandQueueProperty'.
-- As specified for 'clCreateCommandQueue', the 
-- 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' command-queue property determines 
-- whether the commands in a command-queue are executed in-order or 
-- out-of-order. Changing this command-queue property will cause the OpenCL 
-- implementation to block until all previously queued commands in command_queue 
-- have completed. This can be an expensive operation and therefore changes to 
-- the 'CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE' property should be only done 
-- when absolutely necessary.
-- 
-- It is possible that a device(s) becomes unavailable after a context and 
-- command-queues that use this device(s) have been created and commands have 
-- been queued to command-queues. In this case the behavior of OpenCL API calls 
-- that use this context (and command-queues) are considered to be 
-- implementation-defined. The user callback function, if specified when the 
-- context is created, can be used to record appropriate information 
-- when the device becomes unavailable.
clSetCommandQueueProperty :: CLCommandQueue -> [CLCommandQueueProperty] -> Bool 
                          -> IO [CLCommandQueueProperty]
clSetCommandQueueProperty cq xs val = alloca $ \(dat :: Ptr CLCommandQueueProperty_) -> do
  errcode <- fmap ErrorCode $ raw_clSetCommandQueueProperty cq props (fromBool val) dat
  if errcode == clSuccess
    then fmap bitmaskToCommandQueueProperties $ peek dat
    else return []
    where
      props = bitmaskFromFlags xs

-- -----------------------------------------------------------------------------
clEnqueue :: (CLuint -> Ptr CLEvent -> Ptr CLEvent -> IO CLint) -> [CLEvent] -> IO (Either CLError CLEvent)
clEnqueue f [] = alloca $ \event -> do
  errcode <- f 0 nullPtr event
  if errcode == (fromIntegral . fromEnum $ CL_SUCCESS )
    then fmap Right $ peek event
    else return . Left . toEnum . fromIntegral $ errcode
clEnqueue f events = allocaArray nevents $ \pevents -> do
  pokeArray pevents events
  alloca $ \event -> do
    errcode <- f cnevents pevents event
    if errcode == (fromIntegral . fromEnum $ CL_SUCCESS )
      then fmap Right $ peek event
      else return . Left . toEnum . fromIntegral $ errcode
    where
      nevents = length events
      cnevents = fromIntegral nevents

import System.GPU.OpenCL.Types( 
  CLint, CLbool, CLuint, CLCommandQueueProperty_, CLCommandQueueInfo_, 
  CLError(..), CLCommandQueue, CLDeviceID, CLContext, CLCommandQueueProperty(..), 
  CLEvent, CLMem, CLKernel,
  wrapCheckSuccess, wrapPError, wrapGetInfo, getCLValue, getEnumCL,
  bitmaskToCommandQueueProperties, bitmaskFromFlags )

#include <CL/cl.h>

