  * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
 by the OpenCL implementation on the host.
 -}
-clEnqueueTask :: CLCommandQueue -> CLKernel -> [CLEvent] -> IO (Either CLError CLEvent)
+clEnqueueTask :: CLCommandQueue -> CLKernel -> [CLEvent] 
+                 -> IO (Either CLError CLEvent)
 clEnqueueTask cq krn = clEnqueue (raw_clEnqueueTask cq krn)
   
 -- -----------------------------------------------------------------------------
--- | Issues all previously queued OpenCL commands in a command-queue to the 
--- device associated with the command-queue.
--- 'clFlush' only guarantees that all queued commands to command_queue get 
--- issued to the appropriate device. There is no guarantee that they will be 
--- complete after 'clFlush' returns.
--- 
--- 'clFlush' returns 'True' if the function call was executed successfully. It 
--- returns 'False' if command_queue is not a valid command-queue or if there is 
--- a failure to allocate resources required by the OpenCL implementation on the 
--- host.
---
--- Any blocking commands queued in a command-queue such as 'clEnqueueReadImage' 
--- or 'clEnqueueReadBuffer' with blocking_read set to 'True', 
--- 'clEnqueueWriteImage' or 'clEnqueueWriteBuffer' with blocking_write set to 
--- 'True', 'clEnqueueMapImage' or 'clEnqueueMapBuffer' with blocking_map set to 
--- 'True' or 'clWaitForEvents' perform an implicit flush of the command-queue.
---
--- To use event objects that refer to commands enqueued in a command-queue as 
--- event objects to wait on by commands enqueued in a different command-queue, 
--- the application must call a 'clFlush' or any blocking commands that perform 
--- an implicit flush of the command-queue where the commands that refer to these 
--- event objects are enqueued.
+-- | Enqueues a marker command to command_queue. The marker command returns an
+-- event which can be used to queue a wait on this marker event i.e. wait for
+-- all commands queued before the marker command to complete. Returns the event
+-- if the function is successfully executed. It returns
+-- 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue and
+-- returns 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources
+-- required by the OpenCL implementation on the host.
+clEnqueueMarker :: CLCommandQueue -> IO (Either CLError CLEvent)
+clEnqueueMarker cq = alloca $ \event -> do
+  errcode <- raw_clEnqueueMarker cq event
+  if errcode == getCLValue CL_SUCCESS
+    then fmap Right $ peek event
+    else return . Left . getEnumCL $ errcode
+         
+{-| Enqueues a wait for a specific event or a list of events to complete before
+any future commands queued in the command-queue are executed. The context
+associated with events in event_list and command_queue must be the same.
+
+Returns one of the errors below when fails:
+
+ * 'CL_INVALID_COMMAND_QUEUE' if command_queue is not a valid command-queue.
+
+ * 'CL_INVALID_CONTEXT' if the context associated with command_queue and events
+in event_list are not the same.
+
+ * 'CL_INVALID_VALUE' if num_events is zero.
+
+ * 'CL_INVALID_EVENT' if event objects specified in event_list are not valid
+events.
+
+ * 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+by the OpenCL implementation on the host.
+-}
+clEnqueueWaitForEvents :: CLCommandQueue -> [CLEvent] -> IO (Either CLError ())
+clEnqueueWaitForEvents cq [] = do
+  errcode <- raw_clEnqueueWaitForEvents cq 0 nullPtr
+  if errcode == getCLValue CL_SUCCESS
+    then return $ Right ()
+    else return . Left . getEnumCL $ errcode
+clEnqueueWaitForEvents cq events = allocaArray nevents $ \pevents -> do
+  pokeArray pevents events
+  errcode <- raw_clEnqueueWaitForEvents cq cnevents pevents
+  if errcode == getCLValue CL_SUCCESS
+    then return $ Right ()
+    else return . Left . getEnumCL $ errcode
+    where
+      nevents = length events
+      cnevents = fromIntegral nevents
+
+-- | 'clEnqueueBarrier' is a synchronization point that ensures that all queued
+-- commands in command_queue have finished execution before the next batch of
+-- commands can begin execution. It returns 'CL_INVALID_COMMAND_QUEUE' if
+-- command_queue is not a valid command-queue and returns
+-- 'CL_OUT_OF_HOST_MEMORY' if there is a failure to allocate resources required
+-- by the OpenCL implementation on the host.
+clEnqueueBarrier :: CLCommandQueue -> IO (Either CLError ())
+clEnqueueBarrier cq = do
+  errcode <- raw_clEnqueueBarrier cq
+  if errcode == getCLValue CL_SUCCESS
+    then return $ Right ()
+    else return . Left . getEnumCL $ errcode
+  
+-- -----------------------------------------------------------------------------
+{-| Issues all previously queued OpenCL commands in a command-queue to the
+device associated with the command-queue.  'clFlush' only guarantees that all
+queued commands to command_queue get issued to the appropriate device. There is
+no guarantee that they will be complete after 'clFlush' returns.
+
+ 'clFlush' returns 'True' if the function call was executed successfully. It
+returns 'False' if command_queue is not a valid command-queue or if there is a
+failure to allocate resources required by the OpenCL implementation on the host.
+
+ Any blocking commands queued in a command-queue such as 'clEnqueueReadImage' or
+'clEnqueueReadBuffer' with blocking_read set to 'True', 'clEnqueueWriteImage' or
+'clEnqueueWriteBuffer' with blocking_write set to 'True', 'clEnqueueMapImage' or
+'clEnqueueMapBuffer' with blocking_map set to 'True' or 'clWaitForEvents'
+perform an implicit flush of the command-queue.
+
+ To use event objects that refer to commands enqueued in a command-queue as
+event objects to wait on by commands enqueued in a different command-queue, the
+application must call a 'clFlush' or any blocking commands that perform an
+implicit flush of the command-queue where the commands that refer to these event
+objects are enqueued.
+-}
 clFlush :: CLCommandQueue -> IO Bool
 clFlush = wrapCheckSuccess . raw_clFlush
              

  -- * Memory Commands
  clEnqueueReadBuffer, clEnqueueWriteBuffer,
  -- * Executing Kernels
  clEnqueueNDRangeKernel, clEnqueueTask,
  -- * Flush and Finish
  clFlush, clFinish
  ) where

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>

