 -- provided by the MPI implementation. See the documentation for 'ThreadSupport'
 -- for information about what levels are available and their relative ordering.
 -- This function corresponds to @MPI_Init_thread@.
-initThread = {# fun unsafe init_wrapper_thread as init_wrapper_thread_
+{# fun unsafe init_wrapper_thread as initThread
                 {cFromEnum `ThreadSupport', alloca- `ThreadSupport' peekEnum* } -> `()' checkError*- #}
 
-queryThread = {# fun unsafe Query_thread as queryThread_
-                 {alloca- `Bool' peekBool* } -> `()' checkError*- #}
-
-isThreadMain = {# fun unsafe Is_thread_main as isThreadMain_
+{# fun unsafe Query_thread as ^ {alloca- `Bool' peekBool* } -> `()' checkError*- #}
+
+{# fun unsafe Is_thread_main as ^
                  {alloca- `Bool' peekBool* } -> `()' checkError*- #}
 
 -- | Terminate the MPI execution environment.

-- than once for a given MPI program execution. The only MPI functions that may
-- be called before the MPI environment is initialized are 'getVersion',
-- 'initialized' and 'finalized'. This function corresponds to @MPI_Init@.
init = {# fun unsafe init_wrapper as init_wrapper_ {} -> `()' checkError*- #}

-- | Determine if the MPI environment has been initialized. Returns @True@ if the
-- environment has been initialized and @False@ otherwise. This function
-- may be called before the MPI environment has been initialized and after it
-- has been finalized.
-- This function corresponds to @MPI_Initialized@.
initialized = {# fun unsafe Initialized as initialized_ {alloca- `Bool' peekBool*} -> `()' checkError*- #}

-- | Determine if the MPI environment has been finalized. Returns @True@ if the
-- environment has been finalized and @False@ otherwise. This function
-- may be called before the MPI environment has been initialized and after it
-- has been finalized.
-- This function corresponds to @MPI_Finalized@.
finalized = {# fun unsafe Finalized as finalized_ {alloca- `Bool' peekBool*} -> `()' checkError*- #}

-- | Initialize the MPI environment with a /required/ level of thread support.
-- See the documentation for 'init' for more information about MPI initialization.


-- | Cancel a pending communication request.
-- This function corresponds to @MPI_Cancel@.
{# fun unsafe Cancel as ^
            {withRequest* `Request'} -> `()' checkError*- #}
withRequest req f = do alloca $ \ptr -> do poke ptr req
                                           f (castPtr ptr)
{# fun unsafe Scatter as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromRank `Rank', fromComm `Comm'} -> `()' checkError*- #}

{# fun unsafe Gather as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromRank `Rank', fromComm `Comm'} -> `()' checkError*- #}

-- We pass counts/displs as Ptr CInt so that caller could supply nullPtr here
-- which would be impossible if we marshal arrays ourselves here.
{# fun unsafe Scatterv as ^
             { id `BufferPtr', id `Ptr CInt', id `Ptr CInt', fromDatatype `Datatype',
               id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromRank `Rank', fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Gatherv as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Ptr CInt', id `Ptr CInt', fromDatatype `Datatype',
               fromRank `Rank', fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Allgather as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Allgatherv as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Ptr CInt', id `Ptr CInt', fromDatatype `Datatype',
               fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Alltoall as ^
             { id `BufferPtr', id `Count', fromDatatype `Datatype',
               id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Alltoallv as ^
             { id `BufferPtr', id `Ptr CInt', id `Ptr CInt', fromDatatype `Datatype',
               id `BufferPtr', id `Ptr CInt', id `Ptr CInt', fromDatatype `Datatype',
               fromComm `Comm'} -> `()' checkError*- #}
-- Reduce, allreduce and reduceScatter could call back to Haskell
-- via user-defined ops, so they should be imported in "safe" mode
{# fun Reduce as ^
             { id `BufferPtr', id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromOperation `Operation', fromRank `Rank', fromComm `Comm'} -> `()' checkError*- #}
{# fun Allreduce as ^
             { id `BufferPtr', id `BufferPtr', id `Count', fromDatatype `Datatype',
               fromOperation `Operation', fromComm `Comm'} -> `()' checkError*- #}
{# fun Reduce_scatter as ^
             { id `BufferPtr', id `BufferPtr', id `Ptr CInt', fromDatatype `Datatype',
               fromOperation `Operation', fromComm `Comm'} -> `()' checkError*- #}
{# fun unsafe Op_create as ^
              {castFunPtr `FunPtr (Ptr t -> Ptr t -> Ptr CInt -> Ptr Datatype -> IO ())', cFromEnum `Bool', alloca- `Operation' peekOperation*} -> `()' checkError*- #}
opFree = {# call unsafe Op_free as opFree_ #}
{# fun unsafe Wtime as ^ {} -> `Double' realToFrac #}
{# fun unsafe Wtick as ^ {} -> `Double' realToFrac #}

-- | Return the process group from a communicator.
{# fun unsafe Comm_group as ^
               {fromComm `Comm', alloca- `Group' peekGroup*} -> `()' checkError*- #}

groupRank = unsafePerformIO <$> groupRank'
