{-# LANGUAGE TypeApplications #-} -- | Copyright : Will Thompson, Iñaki García Etxebarria and Jonas Platte -- 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 , noRecMutex , -- * Methods -- ** Overloaded methods #method:Overloaded methods# #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.ManagedPtr as B.ManagedPtr import qualified Data.GI.Base.GClosure as B.GClosure import qualified Data.GI.Base.GError as B.GError 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 Data.Text as T 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 -- | Memory-managed wrapper type. newtype RecMutex = RecMutex (ManagedPtr RecMutex) deriving (Eq) instance WrappedPtr RecMutex where wrappedPtrCalloc = callocBytes 16 wrappedPtrCopy = \p -> withManagedPtr p (copyBytes 16 >=> wrapPtr RecMutex) wrappedPtrFree = Just ptr_to_g_free -- | Construct a `RecMutex` struct initialized to zero. newZeroRecMutex :: MonadIO m => m RecMutex newZeroRecMutex = liftIO $ wrappedPtrCalloc >>= wrapPtr RecMutex instance tag ~ 'AttrSet => Constructible RecMutex tag where new _ attrs = do o <- newZeroRecMutex GI.Attributes.set o attrs return o -- | A convenience alias for `Nothing` :: `Maybe` `RecMutex`. noRecMutex :: Maybe RecMutex noRecMutex = Nothing #if defined(ENABLE_OVERLOADING) instance O.HasAttributeList RecMutex type instance O.AttributeList RecMutex = RecMutexAttributeList type RecMutexAttributeList = ('[ ] :: [(Symbol, *)]) #endif -- method RecMutex::clear -- method type : OrdinaryMethod -- Args: [ Arg -- { argCName = "rec_mutex" -- , argType = -- TInterface Name { namespace = "GLib" , name = "RecMutex" } -- , direction = DirectionIn -- , mayBeNull = False -- , argDoc = -- Documentation -- { rawDocText = Just "an initialized #GRecMutex" -- , sinceVersion = Nothing -- } -- , argScope = ScopeTypeInvalid -- , argClosure = -1 -- , argDestroy = -1 -- , argCallerAllocates = 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. -- -- Sine: 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.MethodInfo RecMutexClearMethodInfo RecMutex signature where overloadedMethod = recMutexClear #endif -- method RecMutex::init -- method type : OrdinaryMethod -- Args: [ Arg -- { argCName = "rec_mutex" -- , argType = -- TInterface Name { namespace = "GLib" , name = "RecMutex" } -- , direction = DirectionIn -- , mayBeNull = False -- , argDoc = -- Documentation -- { rawDocText = Just "an uninitialized #GRecMutex" -- , sinceVersion = Nothing -- } -- , argScope = ScopeTypeInvalid -- , argClosure = -1 -- , argDestroy = -1 -- , argCallerAllocates = 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.MethodInfo RecMutexInitMethodInfo RecMutex signature where overloadedMethod = recMutexInit #endif -- method RecMutex::lock -- method type : OrdinaryMethod -- Args: [ Arg -- { argCName = "rec_mutex" -- , argType = -- TInterface Name { namespace = "GLib" , name = "RecMutex" } -- , direction = DirectionIn -- , mayBeNull = False -- , argDoc = -- Documentation -- { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing } -- , argScope = ScopeTypeInvalid -- , argClosure = -1 -- , argDestroy = -1 -- , argCallerAllocates = 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.MethodInfo RecMutexLockMethodInfo RecMutex signature where overloadedMethod = recMutexLock #endif -- method RecMutex::trylock -- method type : OrdinaryMethod -- Args: [ Arg -- { argCName = "rec_mutex" -- , argType = -- TInterface Name { namespace = "GLib" , name = "RecMutex" } -- , direction = DirectionIn -- , mayBeNull = False -- , argDoc = -- Documentation -- { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing } -- , argScope = ScopeTypeInvalid -- , argClosure = -1 -- , argDestroy = -1 -- , argCallerAllocates = 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.MethodInfo RecMutexTrylockMethodInfo RecMutex signature where overloadedMethod = recMutexTrylock #endif -- method RecMutex::unlock -- method type : OrdinaryMethod -- Args: [ Arg -- { argCName = "rec_mutex" -- , argType = -- TInterface Name { namespace = "GLib" , name = "RecMutex" } -- , direction = DirectionIn -- , mayBeNull = False -- , argDoc = -- Documentation -- { rawDocText = Just "a #GRecMutex" , sinceVersion = Nothing } -- , argScope = ScopeTypeInvalid -- , argClosure = -1 -- , argDestroy = -1 -- , argCallerAllocates = 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.MethodInfo RecMutexUnlockMethodInfo RecMutex signature where overloadedMethod = recMutexUnlock #endif #if defined(ENABLE_OVERLOADING) type family ResolveRecMutexMethod (t :: Symbol) (o :: *) :: * 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.MethodInfo 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 #endif