{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (garetxe@gmail.com)

The GRWLock struct is an opaque data structure to represent a
reader-writer lock. It is similar to a #GMutex in that it allows
multiple threads to coordinate access to a shared resource.

The difference to a mutex is that a reader-writer lock discriminates
between read-only ('reader') and full ('writer') access. While only
one thread at a time is allowed write access (by holding the 'writer'
lock via g_rw_lock_writer_lock()), multiple threads can gain
simultaneous read-only access (by holding the 'reader' lock via
g_rw_lock_reader_lock()).

Here is an example for an array with access functions:
|[<!-- language="C" -->
  GRWLock lock;
  GPtrArray *array;

  gpointer
  my_array_get (guint index)
  {
    gpointer retval = NULL;

    if (!array)
      return NULL;

    g_rw_lock_reader_lock (&lock);
    if (index < array->len)
      retval = g_ptr_array_index (array, index);
    g_rw_lock_reader_unlock (&lock);

    return retval;
  }

  void
  my_array_set (guint index, gpointer data)
  {
    g_rw_lock_writer_lock (&lock);

    if (!array)
      array = g_ptr_array_new ();

    if (index >= array->len)
      g_ptr_array_set_size (array, index+1);
    g_ptr_array_index (array, index) = data;

    g_rw_lock_writer_unlock (&lock);
  }
 ]|
This example shows an array which can be accessed by many readers
(the my_array_get() function) simultaneously, whereas the writers
(the my_array_set() function) will only be allowed one at a time
and only if no readers currently access the array. This is because
of the potentially dangerous resizing of the array. Using these
functions is fully multi-thread safe now.

If a #GRWLock is allocated in static storage then it can be used
without initialisation.  Otherwise, you should call
g_rw_lock_init() on it and g_rw_lock_clear() when done.

A GRWLock should only be accessed with the g_rw_lock_ functions.
-}

module GI.GLib.Structs.RWLock
    ( 

-- * Exported types
    RWLock(..)                              ,
    noRWLock                                ,


 -- * Methods
-- ** rWLockClear
    rWLockClear                             ,


-- ** rWLockInit
    rWLockInit                              ,


-- ** rWLockReaderLock
    rWLockReaderLock                        ,


-- ** rWLockReaderTrylock
    rWLockReaderTrylock                     ,


-- ** rWLockReaderUnlock
    rWLockReaderUnlock                      ,


-- ** rWLockWriterLock
    rWLockWriterLock                        ,


-- ** rWLockWriterTrylock
    rWLockWriterTrylock                     ,


-- ** rWLockWriterUnlock
    rWLockWriterUnlock                      ,




    ) where

import Prelude ()
import Data.GI.Base.ShortPrelude

import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map

import GI.GLib.Types
import GI.GLib.Callbacks

newtype RWLock = RWLock (ForeignPtr RWLock)
noRWLock :: Maybe RWLock
noRWLock = Nothing

-- method RWLock::clear
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_clear" g_rw_lock_clear :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockClear ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockClear _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_clear _obj'
    touchManagedPtr _obj
    return ()

-- method RWLock::init
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_init" g_rw_lock_init :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockInit ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockInit _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_init _obj'
    touchManagedPtr _obj
    return ()

-- method RWLock::reader_lock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_reader_lock" g_rw_lock_reader_lock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockReaderLock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockReaderLock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_reader_lock _obj'
    touchManagedPtr _obj
    return ()

-- method RWLock::reader_trylock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TBoolean
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_reader_trylock" g_rw_lock_reader_trylock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO CInt


rWLockReaderTrylock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m Bool
rWLockReaderTrylock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    result <- g_rw_lock_reader_trylock _obj'
    let result' = (/= 0) result
    touchManagedPtr _obj
    return result'

-- method RWLock::reader_unlock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_reader_unlock" g_rw_lock_reader_unlock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockReaderUnlock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockReaderUnlock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_reader_unlock _obj'
    touchManagedPtr _obj
    return ()

-- method RWLock::writer_lock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_writer_lock" g_rw_lock_writer_lock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockWriterLock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockWriterLock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_writer_lock _obj'
    touchManagedPtr _obj
    return ()

-- method RWLock::writer_trylock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TBoolean
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_writer_trylock" g_rw_lock_writer_trylock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO CInt


rWLockWriterTrylock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m Bool
rWLockWriterTrylock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    result <- g_rw_lock_writer_trylock _obj'
    let result' = (/= 0) result
    touchManagedPtr _obj
    return result'

-- method RWLock::writer_unlock
-- method type : OrdinaryMethod
-- Args : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- Lengths : []
-- hInArgs : [Arg {argName = "_obj", argType = TInterface "GLib" "RWLock", direction = DirectionIn, mayBeNull = False, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, transfer = TransferNothing}]
-- returnType : TBasicType TVoid
-- throws : False
-- Skip return : False

foreign import ccall "g_rw_lock_writer_unlock" g_rw_lock_writer_unlock :: 
    Ptr RWLock ->                           -- _obj : TInterface "GLib" "RWLock"
    IO ()


rWLockWriterUnlock ::
    (MonadIO m) =>
    RWLock ->                               -- _obj
    m ()
rWLockWriterUnlock _obj = liftIO $ do
    let _obj' = unsafeManagedPtrGetPtr _obj
    g_rw_lock_writer_unlock _obj'
    touchManagedPtr _obj
    return ()