    module SDL.Raw.Thread (
      -- * Thread Management
      createThread,
      detachThread,
      getThreadID,
      getThreadName,
      setThreadPriority,
      tlsCreate,
      tlsGet,
      tlsSet,
      threadID,
      waitThread,

      -- * Thread Synchronization Primitives
      condBroadcast,
      condSignal,
      condWait,
      condWaitTimeout,
      createCond,
      createMutex,
      createSemaphore,
      destroyCond,
      destroyMutex,
      destroySemaphore,
      lockMutex,
      semPost,
      semTryWait,
      semValue,
      semWait,
      semWaitTimeout,
      tryLockMutex,
      unlockMutex,

      -- * Atomic Operations
      atomicAdd,
      atomicCAS,
      atomicCASPtr,
      atomicDecRef,
      atomicGet,
      atomicGetPtr,
      atomicIncRef,
      atomicLock,
      atomicSet,
      atomicSetPtr,
      atomicTryLock,
      atomicUnlock
    ) where

    import Control.Monad.IO.Class
    import Data.Word
    import Foreign.C.String
    import Foreign.C.Types
    import Foreign.Ptr
    import SDL.Raw.Enum
    import SDL.Raw.Types

    foreign import ccall "SDL.h SDL_CreateThread" createThreadFFI :: ThreadFunction -> CString -> IO (Ptr ())
    foreign import ccall "SDL.h SDL_DetachThread" detachThreadFFI :: Ptr Thread -> IO ()
    foreign import ccall "SDL.h SDL_GetThreadID" getThreadIDFFI :: Ptr Thread -> IO ThreadID
    foreign import ccall "SDL.h SDL_GetThreadName" getThreadNameFFI :: Ptr Thread -> IO CString
    foreign import ccall "SDL.h SDL_SetThreadPriority" setThreadPriorityFFI :: ThreadPriority -> IO CInt
    foreign import ccall "SDL.h SDL_TLSCreate" tlsCreateFFI :: IO TLSID
    foreign import ccall "SDL.h SDL_TLSGet" tlsGetFFI :: TLSID -> IO (Ptr ())
    foreign import ccall "SDL.h SDL_TLSSet" tlsSetFFI :: TLSID -> Ptr () -> FunPtr (Ptr () -> IO ()) -> IO CInt
    foreign import ccall "SDL.h SDL_ThreadID" threadIDFFI :: IO ThreadID
    foreign import ccall "SDL.h SDL_WaitThread" waitThreadFFI :: Ptr Thread -> Ptr CInt -> IO ()

    foreign import ccall "SDL.h SDL_CondBroadcast" condBroadcastFFI :: Ptr Cond -> IO CInt
    foreign import ccall "SDL.h SDL_CondSignal" condSignalFFI :: Ptr Cond -> IO CInt
    foreign import ccall "SDL.h SDL_CondWait" condWaitFFI :: Ptr Cond -> Ptr Mutex -> IO CInt
    foreign import ccall "SDL.h SDL_CondWaitTimeout" condWaitTimeoutFFI :: Ptr Cond -> Ptr Mutex -> Word32 -> IO CInt
    foreign import ccall "SDL.h SDL_CreateCond" createCondFFI :: IO (Ptr Cond)
    foreign import ccall "SDL.h SDL_CreateMutex" createMutexFFI :: IO (Ptr Mutex)
    foreign import ccall "SDL.h SDL_CreateSemaphore" createSemaphoreFFI :: Word32 -> IO (Ptr Sem)
    foreign import ccall "SDL.h SDL_DestroyCond" destroyCondFFI :: Ptr Cond -> IO ()
    foreign import ccall "SDL.h SDL_DestroyMutex" destroyMutexFFI :: Ptr Mutex -> IO ()
    foreign import ccall "SDL.h SDL_DestroySemaphore" destroySemaphoreFFI :: Ptr Sem -> IO ()
    foreign import ccall "SDL.h SDL_LockMutex" lockMutexFFI :: Ptr Mutex -> IO CInt
    foreign import ccall "SDL.h SDL_SemPost" semPostFFI :: Ptr Sem -> IO CInt
    foreign import ccall "SDL.h SDL_SemTryWait" semTryWaitFFI :: Ptr Sem -> IO CInt
    foreign import ccall "SDL.h SDL_SemValue" semValueFFI :: Ptr Sem -> IO Word32
    foreign import ccall "SDL.h SDL_SemWait" semWaitFFI :: Ptr Sem -> IO CInt
    foreign import ccall "SDL.h SDL_SemWaitTimeout" semWaitTimeoutFFI :: Ptr Sem -> Word32 -> IO CInt
    foreign import ccall "SDL.h SDL_TryLockMutex" tryLockMutexFFI :: Ptr Mutex -> IO CInt
    foreign import ccall "SDL.h SDL_UnlockMutex" unlockMutexFFI :: Ptr Mutex -> IO CInt

    foreign import ccall "SDL.h SDL_AtomicAdd" atomicAddFFI :: Ptr Atomic -> CInt -> IO CInt
    foreign import ccall "SDL.h SDL_AtomicCAS" atomicCASFFI :: Ptr Atomic -> CInt -> CInt -> IO Bool
    foreign import ccall "SDL.h SDL_AtomicCASPtr" atomicCASPtrFFI :: Ptr (Ptr ()) -> Ptr () -> Ptr () -> IO Bool
    foreign import ccall "SDL.h SDL_AtomicGet" atomicGetFFI :: Ptr Atomic -> IO CInt
    foreign import ccall "SDL.h SDL_AtomicGetPtr" atomicGetPtrFFI :: Ptr (Ptr ()) -> IO (Ptr ())
    foreign import ccall "SDL.h SDL_AtomicLock" atomicLockFFI :: Ptr SpinLock -> IO ()
    foreign import ccall "SDL.h SDL_AtomicSet" atomicSetFFI :: Ptr Atomic -> CInt -> IO CInt
    foreign import ccall "SDL.h SDL_AtomicSetPtr" atomicSetPtrFFI :: Ptr (Ptr ()) -> Ptr () -> IO (Ptr ())
    foreign import ccall "SDL.h SDL_AtomicTryLock" atomicTryLockFFI :: Ptr SpinLock -> IO Bool
    foreign import ccall "SDL.h SDL_AtomicUnlock" atomicUnlockFFI :: Ptr SpinLock -> IO ()

    createThread :: MonadIO m => ThreadFunction -> CString -> m (Ptr ())
    createThread :: ThreadFunction -> CString -> m (Ptr ())
    createThread v1 :: ThreadFunction
    v1 v2 :: CString
    v2 = IO (Ptr ()) -> m (Ptr ())
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Ptr ()) -> m (Ptr ())) -> IO (Ptr ()) -> m (Ptr ())
    forall a b. (a -> b) -> a -> b
    $ ThreadFunction -> CString -> IO (Ptr ())
    createThreadFFI ThreadFunction
    v1 CString
    v2
    {-# INLINE createThread #-}

    detachThread :: MonadIO m => Ptr Thread -> m ()
    detachThread :: Ptr (Ptr ()) -> m ()
    detachThread v1 :: Ptr (Ptr ())
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ()
    detachThreadFFI Ptr (Ptr ())
    v1
    {-# INLINE detachThread #-}

    getThreadID :: MonadIO m => Ptr Thread -> m ThreadID
    getThreadID :: Ptr (Ptr ()) -> m ThreadID
    getThreadID v1 :: Ptr (Ptr ())
    v1 = IO ThreadID -> m ThreadID
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ThreadID -> m ThreadID) -> IO ThreadID -> m ThreadID
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ThreadID
    getThreadIDFFI Ptr (Ptr ())
    v1
    {-# INLINE getThreadID #-}

    getThreadName :: MonadIO m => Ptr Thread -> m CString
    getThreadName :: Ptr (Ptr ()) -> m CString
    getThreadName v1 :: Ptr (Ptr ())
    v1 = IO CString -> m CString
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CString -> m CString) -> IO CString -> m CString
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CString
    getThreadNameFFI Ptr (Ptr ())
    v1
    {-# INLINE getThreadName #-}

    setThreadPriority :: MonadIO m => ThreadPriority -> m CInt
    setThreadPriority :: ThreadPriority -> m CInt
    setThreadPriority v1 :: ThreadPriority
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ ThreadPriority -> IO CInt
    setThreadPriorityFFI ThreadPriority
    v1
    {-# INLINE setThreadPriority #-}

    tlsCreate :: MonadIO m => m TLSID
    tlsCreate :: m TLSID
    tlsCreate = IO TLSID -> m TLSID
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO TLSID
    tlsCreateFFI
    {-# INLINE tlsCreate #-}

    tlsGet :: MonadIO m => TLSID -> m (Ptr ())
    tlsGet :: TLSID -> m (Ptr ())
    tlsGet v1 :: TLSID
    v1 = IO (Ptr ()) -> m (Ptr ())
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Ptr ()) -> m (Ptr ())) -> IO (Ptr ()) -> m (Ptr ())
    forall a b. (a -> b) -> a -> b
    $ TLSID -> IO (Ptr ())
    tlsGetFFI TLSID
    v1
    {-# INLINE tlsGet #-}

    tlsSet :: MonadIO m => TLSID -> Ptr () -> FunPtr (Ptr () -> IO ()) -> m CInt
    tlsSet :: TLSID -> Ptr () -> FunPtr (Ptr () -> IO ()) -> m CInt
    tlsSet v1 :: TLSID
    v1 v2 :: Ptr ()
    v2 v3 :: FunPtr (Ptr () -> IO ())
    v3 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ TLSID -> Ptr () -> FunPtr (Ptr () -> IO ()) -> IO CInt
    tlsSetFFI TLSID
    v1 Ptr ()
    v2 FunPtr (Ptr () -> IO ())
    v3
    {-# INLINE tlsSet #-}

    threadID :: MonadIO m => m ThreadID
    threadID :: m ThreadID
    threadID = IO ThreadID -> m ThreadID
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ThreadID
    threadIDFFI
    {-# INLINE threadID #-}

    waitThread :: MonadIO m => Ptr Thread -> Ptr CInt -> m ()
    waitThread :: Ptr (Ptr ()) -> Ptr CInt -> m ()
    waitThread v1 :: Ptr (Ptr ())
    v1 v2 :: Ptr CInt
    v2 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> Ptr CInt -> IO ()
    waitThreadFFI Ptr (Ptr ())
    v1 Ptr CInt
    v2
    {-# INLINE waitThread #-}

    condBroadcast :: MonadIO m => Ptr Cond -> m CInt
    condBroadcast :: Ptr (Ptr ()) -> m CInt
    condBroadcast v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    condBroadcastFFI Ptr (Ptr ())
    v1
    {-# INLINE condBroadcast #-}

    condSignal :: MonadIO m => Ptr Cond -> m CInt
    condSignal :: Ptr (Ptr ()) -> m CInt
    condSignal v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    condSignalFFI Ptr (Ptr ())
    v1
    {-# INLINE condSignal #-}

    condWait :: MonadIO m => Ptr Cond -> Ptr Mutex -> m CInt
    condWait :: Ptr (Ptr ()) -> Ptr (Ptr ()) -> m CInt
    condWait v1 :: Ptr (Ptr ())
    v1 v2 :: Ptr (Ptr ())
    v2 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> Ptr (Ptr ()) -> IO CInt
    condWaitFFI Ptr (Ptr ())
    v1 Ptr (Ptr ())
    v2
    {-# INLINE condWait #-}

    condWaitTimeout :: MonadIO m => Ptr Cond -> Ptr Mutex -> Word32 -> m CInt
    condWaitTimeout :: Ptr (Ptr ()) -> Ptr (Ptr ()) -> ThreadPriority -> m CInt
    condWaitTimeout v1 :: Ptr (Ptr ())
    v1 v2 :: Ptr (Ptr ())
    v2 v3 :: ThreadPriority
    v3 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> Ptr (Ptr ()) -> ThreadPriority -> IO CInt
    condWaitTimeoutFFI Ptr (Ptr ())
    v1 Ptr (Ptr ())
    v2 ThreadPriority
    v3
    {-# INLINE condWaitTimeout #-}

    createCond :: MonadIO m => m (Ptr Cond)
    createCond :: m (Ptr (Ptr ()))
    createCond = IO (Ptr (Ptr ())) -> m (Ptr (Ptr ()))
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO (Ptr (Ptr ()))
    createCondFFI
    {-# INLINE createCond #-}

    createMutex :: MonadIO m => m (Ptr Mutex)
    createMutex :: m (Ptr (Ptr ()))
    createMutex = IO (Ptr (Ptr ())) -> m (Ptr (Ptr ()))
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO (Ptr (Ptr ()))
    createMutexFFI
    {-# INLINE createMutex #-}

    createSemaphore :: MonadIO m => Word32 -> m (Ptr Sem)
    createSemaphore :: ThreadPriority -> m (Ptr (Ptr ()))
    createSemaphore v1 :: ThreadPriority
    v1 = IO (Ptr (Ptr ())) -> m (Ptr (Ptr ()))
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Ptr (Ptr ())) -> m (Ptr (Ptr ())))
    -> IO (Ptr (Ptr ())) -> m (Ptr (Ptr ()))
    forall a b. (a -> b) -> a -> b
    $ ThreadPriority -> IO (Ptr (Ptr ()))
    createSemaphoreFFI ThreadPriority
    v1
    {-# INLINE createSemaphore #-}

    destroyCond :: MonadIO m => Ptr Cond -> m ()
    destroyCond :: Ptr (Ptr ()) -> m ()
    destroyCond v1 :: Ptr (Ptr ())
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ()
    destroyCondFFI Ptr (Ptr ())
    v1
    {-# INLINE destroyCond #-}

    destroyMutex :: MonadIO m => Ptr Mutex -> m ()
    destroyMutex :: Ptr (Ptr ()) -> m ()
    destroyMutex v1 :: Ptr (Ptr ())
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ()
    destroyMutexFFI Ptr (Ptr ())
    v1
    {-# INLINE destroyMutex #-}

    destroySemaphore :: MonadIO m => Ptr Sem -> m ()
    destroySemaphore :: Ptr (Ptr ()) -> m ()
    destroySemaphore v1 :: Ptr (Ptr ())
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ()
    destroySemaphoreFFI Ptr (Ptr ())
    v1
    {-# INLINE destroySemaphore #-}

    lockMutex :: MonadIO m => Ptr Mutex -> m CInt
    lockMutex :: Ptr (Ptr ()) -> m CInt
    lockMutex v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    lockMutexFFI Ptr (Ptr ())
    v1
    {-# INLINE lockMutex #-}

    semPost :: MonadIO m => Ptr Sem -> m CInt
    semPost :: Ptr (Ptr ()) -> m CInt
    semPost v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    semPostFFI Ptr (Ptr ())
    v1
    {-# INLINE semPost #-}

    semTryWait :: MonadIO m => Ptr Sem -> m CInt
    semTryWait :: Ptr (Ptr ()) -> m CInt
    semTryWait v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    semTryWaitFFI Ptr (Ptr ())
    v1
    {-# INLINE semTryWait #-}

    semValue :: MonadIO m => Ptr Sem -> m Word32
    semValue :: Ptr (Ptr ()) -> m ThreadPriority
    semValue v1 :: Ptr (Ptr ())
    v1 = IO ThreadPriority -> m ThreadPriority
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ThreadPriority -> m ThreadPriority)
    -> IO ThreadPriority -> m ThreadPriority
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO ThreadPriority
    semValueFFI Ptr (Ptr ())
    v1
    {-# INLINE semValue #-}

    semWait :: MonadIO m => Ptr Sem -> m CInt
    semWait :: Ptr (Ptr ()) -> m CInt
    semWait v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    semWaitFFI Ptr (Ptr ())
    v1
    {-# INLINE semWait #-}

    semWaitTimeout :: MonadIO m => Ptr Sem -> Word32 -> m CInt
    semWaitTimeout :: Ptr (Ptr ()) -> ThreadPriority -> m CInt
    semWaitTimeout v1 :: Ptr (Ptr ())
    v1 v2 :: ThreadPriority
    v2 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> ThreadPriority -> IO CInt
    semWaitTimeoutFFI Ptr (Ptr ())
    v1 ThreadPriority
    v2
    {-# INLINE semWaitTimeout #-}

    tryLockMutex :: MonadIO m => Ptr Mutex -> m CInt
    tryLockMutex :: Ptr (Ptr ()) -> m CInt
    tryLockMutex v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    tryLockMutexFFI Ptr (Ptr ())
    v1
    {-# INLINE tryLockMutex #-}

    unlockMutex :: MonadIO m => Ptr Mutex -> m CInt
    unlockMutex :: Ptr (Ptr ()) -> m CInt
    unlockMutex v1 :: Ptr (Ptr ())
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO CInt
    unlockMutexFFI Ptr (Ptr ())
    v1
    {-# INLINE unlockMutex #-}

    atomicAdd :: MonadIO m => Ptr Atomic -> CInt -> m CInt
    atomicAdd :: Ptr Atomic -> CInt -> m CInt
    atomicAdd v1 :: Ptr Atomic
    v1 v2 :: CInt
    v2 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr Atomic -> CInt -> IO CInt
    atomicAddFFI Ptr Atomic
    v1 CInt
    v2
    {-# INLINE atomicAdd #-}

    atomicCAS :: MonadIO m => Ptr Atomic -> CInt -> CInt -> m Bool
    atomicCAS :: Ptr Atomic -> CInt -> CInt -> m Bool
    atomicCAS v1 :: Ptr Atomic
    v1 v2 :: CInt
    v2 v3 :: CInt
    v3 = IO Bool -> m Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
    forall a b. (a -> b) -> a -> b
    $ Ptr Atomic -> CInt -> CInt -> IO Bool
    atomicCASFFI Ptr Atomic
    v1 CInt
    v2 CInt
    v3
    {-# INLINE atomicCAS #-}

    atomicCASPtr :: MonadIO m => Ptr (Ptr ()) -> Ptr () -> Ptr () -> m Bool
    atomicCASPtr :: Ptr (Ptr ()) -> Ptr () -> Ptr () -> m Bool
    atomicCASPtr v1 :: Ptr (Ptr ())
    v1 v2 :: Ptr ()
    v2 v3 :: Ptr ()
    v3 = IO Bool -> m Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> Ptr () -> Ptr () -> IO Bool
    atomicCASPtrFFI Ptr (Ptr ())
    v1 Ptr ()
    v2 Ptr ()
    v3
    {-# INLINE atomicCASPtr #-}

    atomicDecRef :: Ptr Atomic -> IO Bool
    atomicDecRef :: Ptr Atomic -> IO Bool
    atomicDecRef a :: Ptr Atomic
    a = do
      CInt
    old <- Ptr Atomic -> CInt -> IO CInt
    forall (m :: * -> *). MonadIO m => Ptr Atomic -> CInt -> m CInt
    atomicAdd Ptr Atomic
    a (-1)
      Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool -> IO Bool) -> Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ CInt
    old CInt -> CInt -> Bool
    forall a. Eq a => a -> a -> Bool
    == 1
    {-# INLINE atomicDecRef #-}

    atomicGet :: MonadIO m => Ptr Atomic -> m CInt
    atomicGet :: Ptr Atomic -> m CInt
    atomicGet v1 :: Ptr Atomic
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr Atomic -> IO CInt
    atomicGetFFI Ptr Atomic
    v1
    {-# INLINE atomicGet #-}

    atomicGetPtr :: MonadIO m => Ptr (Ptr ()) -> m (Ptr ())
    atomicGetPtr :: Ptr (Ptr ()) -> m (Ptr ())
    atomicGetPtr v1 :: Ptr (Ptr ())
    v1 = IO (Ptr ()) -> m (Ptr ())
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Ptr ()) -> m (Ptr ())) -> IO (Ptr ()) -> m (Ptr ())
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> IO (Ptr ())
    atomicGetPtrFFI Ptr (Ptr ())
    v1
    {-# INLINE atomicGetPtr #-}

    atomicIncRef :: Ptr Atomic -> IO CInt
    atomicIncRef :: Ptr Atomic -> IO CInt
    atomicIncRef a :: Ptr Atomic
    a = Ptr Atomic -> CInt -> IO CInt
    forall (m :: * -> *). MonadIO m => Ptr Atomic -> CInt -> m CInt
    atomicAdd Ptr Atomic
    a 1
    {-# INLINE atomicIncRef #-}

    atomicLock :: MonadIO m => Ptr SpinLock -> m ()
    atomicLock :: Ptr CInt -> m ()
    atomicLock v1 :: Ptr CInt
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr CInt -> IO ()
    atomicLockFFI Ptr CInt
    v1
    {-# INLINE atomicLock #-}

    atomicSet :: MonadIO m => Ptr Atomic -> CInt -> m CInt
    atomicSet :: Ptr Atomic -> CInt -> m CInt
    atomicSet v1 :: Ptr Atomic
    v1 v2 :: CInt
    v2 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ Ptr Atomic -> CInt -> IO CInt
    atomicSetFFI Ptr Atomic
    v1 CInt
    v2
    {-# INLINE atomicSet #-}

    atomicSetPtr :: MonadIO m => Ptr (Ptr ()) -> Ptr () -> m (Ptr ())
    atomicSetPtr :: Ptr (Ptr ()) -> Ptr () -> m (Ptr ())
    atomicSetPtr v1 :: Ptr (Ptr ())
    v1 v2 :: Ptr ()
    v2 = IO (Ptr ()) -> m (Ptr ())
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Ptr ()) -> m (Ptr ())) -> IO (Ptr ()) -> m (Ptr ())
    forall a b. (a -> b) -> a -> b
    $ Ptr (Ptr ()) -> Ptr () -> IO (Ptr ())
    atomicSetPtrFFI Ptr (Ptr ())
    v1 Ptr ()
    v2
    {-# INLINE atomicSetPtr #-}

    atomicTryLock :: MonadIO m => Ptr SpinLock -> m Bool
    atomicTryLock :: Ptr CInt -> m Bool
    atomicTryLock v1 :: Ptr CInt
    v1 = IO Bool -> m Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
    forall a b. (a -> b) -> a -> b
    $ Ptr CInt -> IO Bool
    atomicTryLockFFI Ptr CInt
    v1
    {-# INLINE atomicTryLock #-}

    atomicUnlock :: MonadIO m => Ptr SpinLock -> m ()
    atomicUnlock :: Ptr CInt -> m ()
    atomicUnlock v1 :: Ptr CInt
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr CInt -> IO ()
    atomicUnlockFFI Ptr CInt
    v1
    {-# INLINE atomicUnlock #-}