{-# LANGUAGE TypeApplications #-}


-- | Copyright  : Will Thompson and Iñaki García Etxebarria
-- License    : LGPL-2.1
-- Maintainer : Iñaki García Etxebarria
-- 
-- The GRecMutex struct is an opaque data structure to represent a
-- recursive mutex. It is similar to a t'GI.GLib.Unions.Mutex.Mutex' with the difference
-- that it is possible to lock a GRecMutex multiple times in the same
-- thread without deadlock. When doing so, care has to be taken to
-- unlock the recursive mutex as often as it has been locked.
-- 
-- If a t'GI.GLib.Structs.RecMutex.RecMutex' is allocated in static storage then it can be used
-- without initialisation.  Otherwise, you should call
-- 'GI.GLib.Structs.RecMutex.recMutexInit' on it and 'GI.GLib.Structs.RecMutex.recMutexClear' when done.
-- 
-- A GRecMutex should only be accessed with the
-- g_rec_mutex_ functions.
-- 
-- /Since: 2.32/

#if (MIN_VERSION_haskell_gi_overloading(1,0,0) && !defined(__HADDOCK_VERSION__))
#define ENABLE_OVERLOADING
#endif

module GI.GLib.Structs.RecMutex
    ( 

-- * Exported types
    RecMutex(..)                            ,
    newZeroRecMutex                         ,


 -- * Methods
-- | 
-- 
--  === __Click to display all available methods, including inherited ones__
-- ==== Methods
-- [clear]("GI.GLib.Structs.RecMutex#g:method:clear"), [init]("GI.GLib.Structs.RecMutex#g:method:init"), [lock]("GI.GLib.Structs.RecMutex#g:method:lock"), [trylock]("GI.GLib.Structs.RecMutex#g:method:trylock"), [unlock]("GI.GLib.Structs.RecMutex#g:method:unlock").
-- 
-- ==== Getters
-- /None/.
-- 
-- ==== Setters
-- /None/.

#if defined(ENABLE_OVERLOADING)
    ResolveRecMutexMethod                   ,
#endif

-- ** clear #method:clear#

#if defined(ENABLE_OVERLOADING)
    RecMutexClearMethodInfo                 ,
#endif
    recMutexClear                           ,


-- ** init #method:init#

#if defined(ENABLE_OVERLOADING)
    RecMutexInitMethodInfo                  ,
#endif
    recMutexInit                            ,


-- ** lock #method:lock#

#if defined(ENABLE_OVERLOADING)
    RecMutexLockMethodInfo                  ,
#endif
    recMutexLock                            ,


-- ** trylock #method:trylock#

#if defined(ENABLE_OVERLOADING)
    RecMutexTrylockMethodInfo               ,
#endif
    recMutexTrylock                         ,


-- ** unlock #method:unlock#

#if defined(ENABLE_OVERLOADING)
    RecMutexUnlockMethodInfo                ,
#endif
    recMutexUnlock                          ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.BasicTypes as B.Types
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GArray as B.GArray
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GHashTable as B.GHT
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
import qualified Data.GI.Base.Signals as B.Signals
import qualified Control.Monad.IO.Class as MIO
import qualified Data.Coerce as Coerce
import qualified Data.Text as T
import qualified Data.Kind as DK
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP
import qualified GHC.OverloadedLabels as OL
import qualified GHC.Records as R
import qualified Data.Word as DW
import qualified Data.Int as DI
import qualified System.Posix.Types as SPT
import qualified Foreign.C.Types as FCT

-- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/23392
#if MIN_VERSION_base(4,18,0)

#else

#endif

-- | Memory-managed wrapper type.
newtype RecMutex = RecMutex (SP.ManagedPtr RecMutex)
    deriving (Eq)

instance SP.ManagedPtrNewtype RecMutex where
    toManagedPtr (RecMutex p) = p

instance BoxedPtr RecMutex where
    boxedPtrCopy = \p -> B.ManagedPtr.withManagedPtr p (copyBytes 16 >=> B.ManagedPtr.wrapPtr RecMutex)
    boxedPtrFree = \x -> SP.withManagedPtr x SP.freeMem
instance CallocPtr RecMutex where
    boxedPtrCalloc = callocBytes 16


-- | Construct a t'RecMutex' struct initialized to zero.
newZeroRecMutex :: MonadIO m => m RecMutex
newZeroRecMutex = liftIO $ boxedPtrCalloc >>= wrapPtr RecMutex

instance tag ~ 'AttrSet => Constructible RecMutex tag where
    new _ attrs = do
        o <- newZeroRecMutex
        GI.Attributes.set o attrs
        return o



#if defined(ENABLE_OVERLOADING)
instance O.HasAttributeList RecMutex
type instance O.AttributeList RecMutex = RecMutexAttributeList
type RecMutexAttributeList = ('[ ] :: [(Symbol, DK.Type)])
#endif

-- method RecMutex::clear
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "rec_mutex"
--           , argType =
--               TInterface Name { namespace = "GLib" , name = "RecMutex" }
--           , argCType = Just "GRecMutex*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "an initialized #GRecMutex"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_rec_mutex_clear" g_rec_mutex_clear :: 
    Ptr RecMutex ->                         -- rec_mutex : TInterface (Name {namespace = "GLib", name = "RecMutex"})
    IO ()

-- | Frees the resources allocated to a recursive mutex with
-- 'GI.GLib.Structs.RecMutex.recMutexInit'.
-- 
-- This function should not be used with a t'GI.GLib.Structs.RecMutex.RecMutex' that has been
-- statically allocated.
-- 
-- Calling 'GI.GLib.Structs.RecMutex.recMutexClear' on a locked recursive mutex leads
-- to undefined behaviour.
-- 
-- /Since: 2.32/
recMutexClear ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    RecMutex
    -- ^ /@recMutex@/: an initialized t'GI.GLib.Structs.RecMutex.RecMutex'
    -> m ()
recMutexClear recMutex = liftIO $ do
    recMutex' <- unsafeManagedPtrGetPtr recMutex
    g_rec_mutex_clear recMutex'
    touchManagedPtr recMutex
    return ()

#if defined(ENABLE_OVERLOADING)
data RecMutexClearMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod RecMutexClearMethodInfo RecMutex signature where
    overloadedMethod = recMutexClear

instance O.OverloadedMethodInfo RecMutexClearMethodInfo RecMutex where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.RecMutex.recMutexClear",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-RecMutex.html#v:recMutexClear"
        })


#endif

-- method RecMutex::init
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "rec_mutex"
--           , argType =
--               TInterface Name { namespace = "GLib" , name = "RecMutex" }
--           , argCType = Just "GRecMutex*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "an uninitialized #GRecMutex"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_rec_mutex_init" g_rec_mutex_init :: 
    Ptr RecMutex ->                         -- rec_mutex : TInterface (Name {namespace = "GLib", name = "RecMutex"})
    IO ()

-- | Initializes a t'GI.GLib.Structs.RecMutex.RecMutex' so that it can be used.
-- 
-- This function is useful to initialize a recursive mutex
-- that has been allocated on the stack, or as part of a larger
-- structure.
-- 
-- It is not necessary to initialise a recursive mutex that has been
-- statically allocated.
-- 
-- 
-- === /C code/
-- >
-- >  typedef struct {
-- >    GRecMutex m;
-- >    ...
-- >  } Blob;
-- >
-- >Blob *b;
-- >
-- >b = g_new (Blob, 1);
-- >g_rec_mutex_init (&b->m);
-- 
-- 
-- Calling 'GI.GLib.Structs.RecMutex.recMutexInit' on an already initialized t'GI.GLib.Structs.RecMutex.RecMutex'
-- leads to undefined behaviour.
-- 
-- To undo the effect of 'GI.GLib.Structs.RecMutex.recMutexInit' when a recursive mutex
-- is no longer needed, use 'GI.GLib.Structs.RecMutex.recMutexClear'.
-- 
-- /Since: 2.32/
recMutexInit ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    RecMutex
    -- ^ /@recMutex@/: an uninitialized t'GI.GLib.Structs.RecMutex.RecMutex'
    -> m ()
recMutexInit recMutex = liftIO $ do
    recMutex' <- unsafeManagedPtrGetPtr recMutex
    g_rec_mutex_init recMutex'
    touchManagedPtr recMutex
    return ()

#if defined(ENABLE_OVERLOADING)
data RecMutexInitMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod RecMutexInitMethodInfo RecMutex signature where
    overloadedMethod = recMutexInit

instance O.OverloadedMethodInfo RecMutexInitMethodInfo RecMutex where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.RecMutex.recMutexInit",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-RecMutex.html#v:recMutexInit"
        })


#endif

-- method RecMutex::lock
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "rec_mutex"
--           , argType =
--               TInterface Name { namespace = "GLib" , name = "RecMutex" }
--           , argCType = Just "GRecMutex*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_rec_mutex_lock" g_rec_mutex_lock :: 
    Ptr RecMutex ->                         -- rec_mutex : TInterface (Name {namespace = "GLib", name = "RecMutex"})
    IO ()

-- | Locks /@recMutex@/. If /@recMutex@/ is already locked by another
-- thread, the current thread will block until /@recMutex@/ is
-- unlocked by the other thread. If /@recMutex@/ is already locked
-- by the current thread, the \'lock count\' of /@recMutex@/ is increased.
-- The mutex will only become available again when it is unlocked
-- as many times as it has been locked.
-- 
-- /Since: 2.32/
recMutexLock ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    RecMutex
    -- ^ /@recMutex@/: a t'GI.GLib.Structs.RecMutex.RecMutex'
    -> m ()
recMutexLock recMutex = liftIO $ do
    recMutex' <- unsafeManagedPtrGetPtr recMutex
    g_rec_mutex_lock recMutex'
    touchManagedPtr recMutex
    return ()

#if defined(ENABLE_OVERLOADING)
data RecMutexLockMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod RecMutexLockMethodInfo RecMutex signature where
    overloadedMethod = recMutexLock

instance O.OverloadedMethodInfo RecMutexLockMethodInfo RecMutex where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.RecMutex.recMutexLock",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-RecMutex.html#v:recMutexLock"
        })


#endif

-- method RecMutex::trylock
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "rec_mutex"
--           , argType =
--               TInterface Name { namespace = "GLib" , name = "RecMutex" }
--           , argCType = Just "GRecMutex*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Just (TBasicType TBoolean)
-- throws : False
-- Skip return : False

foreign import ccall "g_rec_mutex_trylock" g_rec_mutex_trylock :: 
    Ptr RecMutex ->                         -- rec_mutex : TInterface (Name {namespace = "GLib", name = "RecMutex"})
    IO CInt

-- | Tries to lock /@recMutex@/. If /@recMutex@/ is already locked
-- by another thread, it immediately returns 'P.False'. Otherwise
-- it locks /@recMutex@/ and returns 'P.True'.
-- 
-- /Since: 2.32/
recMutexTrylock ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    RecMutex
    -- ^ /@recMutex@/: a t'GI.GLib.Structs.RecMutex.RecMutex'
    -> m Bool
    -- ^ __Returns:__ 'P.True' if /@recMutex@/ could be locked
recMutexTrylock recMutex = liftIO $ do
    recMutex' <- unsafeManagedPtrGetPtr recMutex
    result <- g_rec_mutex_trylock recMutex'
    let result' = (/= 0) result
    touchManagedPtr recMutex
    return result'

#if defined(ENABLE_OVERLOADING)
data RecMutexTrylockMethodInfo
instance (signature ~ (m Bool), MonadIO m) => O.OverloadedMethod RecMutexTrylockMethodInfo RecMutex signature where
    overloadedMethod = recMutexTrylock

instance O.OverloadedMethodInfo RecMutexTrylockMethodInfo RecMutex where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.RecMutex.recMutexTrylock",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-RecMutex.html#v:recMutexTrylock"
        })


#endif

-- method RecMutex::unlock
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "rec_mutex"
--           , argType =
--               TInterface Name { namespace = "GLib" , name = "RecMutex" }
--           , argCType = Just "GRecMutex*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_rec_mutex_unlock" g_rec_mutex_unlock :: 
    Ptr RecMutex ->                         -- rec_mutex : TInterface (Name {namespace = "GLib", name = "RecMutex"})
    IO ()

-- | Unlocks /@recMutex@/. If another thread is blocked in a
-- 'GI.GLib.Structs.RecMutex.recMutexLock' call for /@recMutex@/, it will become unblocked
-- and can lock /@recMutex@/ itself.
-- 
-- Calling 'GI.GLib.Structs.RecMutex.recMutexUnlock' on a recursive mutex that is not
-- locked by the current thread leads to undefined behaviour.
-- 
-- /Since: 2.32/
recMutexUnlock ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    RecMutex
    -- ^ /@recMutex@/: a t'GI.GLib.Structs.RecMutex.RecMutex'
    -> m ()
recMutexUnlock recMutex = liftIO $ do
    recMutex' <- unsafeManagedPtrGetPtr recMutex
    g_rec_mutex_unlock recMutex'
    touchManagedPtr recMutex
    return ()

#if defined(ENABLE_OVERLOADING)
data RecMutexUnlockMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod RecMutexUnlockMethodInfo RecMutex signature where
    overloadedMethod = recMutexUnlock

instance O.OverloadedMethodInfo RecMutexUnlockMethodInfo RecMutex where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.RecMutex.recMutexUnlock",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-RecMutex.html#v:recMutexUnlock"
        })


#endif

#if defined(ENABLE_OVERLOADING)
type family ResolveRecMutexMethod (t :: Symbol) (o :: DK.Type) :: DK.Type where
    ResolveRecMutexMethod "clear" o = RecMutexClearMethodInfo
    ResolveRecMutexMethod "init" o = RecMutexInitMethodInfo
    ResolveRecMutexMethod "lock" o = RecMutexLockMethodInfo
    ResolveRecMutexMethod "trylock" o = RecMutexTrylockMethodInfo
    ResolveRecMutexMethod "unlock" o = RecMutexUnlockMethodInfo
    ResolveRecMutexMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveRecMutexMethod t RecMutex, O.OverloadedMethod info RecMutex p) => OL.IsLabel t (RecMutex -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod @info
#else
    fromLabel _ = O.overloadedMethod @info
#endif

#if MIN_VERSION_base(4,13,0)
instance (info ~ ResolveRecMutexMethod t RecMutex, O.OverloadedMethod info RecMutex p, R.HasField t RecMutex p) => R.HasField t RecMutex p where
    getField = O.overloadedMethod @info

#endif

instance (info ~ ResolveRecMutexMethod t RecMutex, O.OverloadedMethodInfo info RecMutex) => OL.IsLabel t (O.MethodProxy info RecMutex) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.MethodProxy
#else
    fromLabel _ = O.MethodProxy
#endif

#endif


