/*

  silcmutex.h

  Author: Pekka Riikonen <priikone@silcnet.org>

  Copyright (C) 2001 - 2007 Pekka Riikonen

  The contents of this file are subject to one of the Licenses specified 
  in the COPYING file;  You may not use this file except in compliance 
  with the License.

  The software distributed under the License is distributed on an "AS IS"
  basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
  KIND, either expressed or implied.  See the COPYING file for more
  information.

*/

/****h* silcutil/SILC Mutex Interface
 *
 * DESCRIPTION
 *
 * Interface for mutual exclusion locks and read/write locks.  This is
 * platform independent interface for applications that need concurrency
 * control.
 *
 ***/

#ifndef SILCMUTEX_H
#define SILCMUTEX_H

/****s* silcutil/SilcMutexAPI/SilcMutex
 *
 * NAME
 *
 *    typedef struct SilcMutexStruct *SilcMutex;
 *
 * DESCRIPTION
 *
 *    This context is the actual SILC Mutex and is allocated
 *    by silc_mutex_alloc and given as argument to all silc_mutex_*
 *    functions.  It is freed by the silc_mutex_free function.
 *
 ***/
typedef struct SilcMutexStruct *SilcMutex;

/****s* silcutil/SilcMutexAPI/SilcRwLock
 *
 * NAME
 *
 *    typedef struct SilcRwLockStruct *SilcRwLock;
 *
 * DESCRIPTION
 *
 *    This context is the actual SILC read/write lock and is allocated
 *    by silc_rwlock_alloc and given as argument to all silc_rwlock_*
 *    functions.  It is freed by the silc_rwlock_free function.
 *
 ***/
typedef struct SilcRwLockStruct *SilcRwLock;

/****f* silcutil/SilcMutexAPI/silc_mutex_alloc
 *
 * SYNOPSIS
 *
 *    SilcBool silc_mutex_alloc(SilcMutex *mutex);
 *
 * DESCRIPTION
 *
 *    Allocates SILC Mutex object.  The mutex object must be allocated
 *    before it can be used.  It is freed by the silc_mutex_free function.
 *    This returns TRUE and allocated mutex in to the `mutex' and FALSE
 *    on error.  If threads support is not compiled in this returns FALSE,
 *    but should not be considered as an error.
 *
 ***/
SilcBool silc_mutex_alloc(SilcMutex *mutex);

/****f* silcutil/SilcMutexAPI/silc_mutex_free
 *
 * SYNOPSIS
 *
 *    void silc_mutex_free(SilcMutex mutex);
 *
 * DESCRIPTION
 *
 *    Free SILC Mutex object and frees all allocated memory.  If `mutex'
 *    is NULL this function has no effect.
 *
 ***/
void silc_mutex_free(SilcMutex mutex);

/****f* silcutil/SilcMutexAPI/silc_mutex_lock
 *
 * SYNOPSIS
 *
 *    void silc_mutex_lock(SilcMutex mutex);
 *
 * DESCRIPTION
 *
 *    Locks the mutex. If the mutex is locked by another thread the
 *    current thread will block until the other thread has issued
 *    silc_mutex_unlock for the mutex.  If `mutex' is NULL this function
 *    has no effect.
 *
 * NOTES
 *
 *    The caller must not call silc_mutex_lock for mutex that has been
 *    already locked in the current thread.  In this case deadlock will
 *    occur.
 *
 ***/
void silc_mutex_lock(SilcMutex mutex);

/****f* silcutil/SilcMutexAPI/silc_mutex_unlock
 *
 * SYNOPSIS
 *
 *    void silc_mutex_unlock(SilcMutex mutex);
 *
 * DESCRIPTION
 *
 *    Unlocks the mutex and thus releases it for another thread that
 *    may be waiting for the lock.  If `mutex' is NULL this function
 *    has no effect.
 *
 * NOTES
 *
 *    The caller must not call the silc_mutex_unlock for an unlocked
 *    mutex or mutex not locked by the current thread.
 *
 ***/
void silc_mutex_unlock(SilcMutex mutex);

/****f* silcutil/SilcMutexAPI/silc_mutex_assert_locked
 *
 * SYNOPSIS
 *
 *    void silc_mutex_assert_locked(SilcMutex mutex);
 *
 * DESCRIPTION
 *
 *    Asserts that the `mutex' is locked.  It is fatal error if the mutex
 *    is not locked.  If debugging is not compiled in this function has
 *    no effect (SILC_DEBUG define).
 *
 ***/
void silc_mutex_assert_locked(SilcMutex mutex);

/****f* silcutil/SilcMutexAPI/silc_rwlock_alloc
 *
 * SYNOPSIS
 *
 *    SilcBool silc_rwlock_alloc(SilcRwLock *rwlock);
 *
 * DESCRIPTION
 *
 *    Allocates SILC read/write lock.  The read/write lock must be allocated
 *    before it can be used.  It is freed by the silc_rwlock_free function.
 *    This returns TRUE and allocated read/write lock in to the `rwlock' and
 *    FALSE on error.
 *
 ***/
SilcBool silc_rwlock_alloc(SilcRwLock *rwlock);

/****f* silcutil/SilcRwLockAPI/silc_rwlock_free
 *
 * SYNOPSIS
 *
 *    void silc_rwlock_free(SilcRwLock rwlock);
 *
 * DESCRIPTION
 *
 *    Free SILC Rwlock object and frees all allocated memory.  If `rwlock'
 *    is NULL this function has no effect.
 *
 ***/
void silc_rwlock_free(SilcRwLock rwlock);

/****f* silcutil/SilcRwLockAPI/silc_rwlock_rdlock
 *
 * SYNOPSIS
 *
 *    void silc_rwlock_rdlock(SilcRwLock rwlock);
 *
 * DESCRIPTION
 *
 *    Acquires read lock of the read/write lock `rwlock'.  If the `rwlock'
 *    is locked by a writer the current thread will block until the other
 *    thread has issued silc_rwlock_unlock for the `rwlock'.  This function
 *    may be called multiple times to acquire the read lock.  There must be
 *    same number of silc_rwlock_unlock calls.  If `rwlock' is NULL this
 *    function has no effect.
 *
 ***/
void silc_rwlock_rdlock(SilcRwLock rwlock);

/****f* silcutil/SilcRwLockAPI/silc_rwlock_wrlock
 *
 * SYNOPSIS
 *
 *    void silc_rwlock_wrlock(SilcRwLock rwlock);
 *
 * DESCRIPTION
 *
 *    Acquires write lock of the read/write lock `rwlock'.  If the `rwlock'
 *    is locked by a writer or a reader the current thread will block until
 *    the other thread(s) have issued silc_rwlock_unlock for the `rwlock'.
 *    A thread may acquire the write lock only once.  A deadlock may occur
 *    if thread attempts to acquire the write lock when it has already done
 *    so.  If `rwlock' is NULL this function has no effect.
 *
 ***/
void silc_rwlock_wrlock(SilcRwLock rwlock);

/****f* silcutil/SilcRwLockAPI/silc_rwlock_unlock
 *
 * SYNOPSIS
 *
 *    void silc_rwlock_unlock(SilcRwLock rwlock);
 *
 * DESCRIPTION
 *
 *    Releases the lock of the read/write lock `rwlock'.  If `rwlock' was
 *    locked by a writer this will release the writer lock.  Otherwise this
 *    releases the reader lock.  If `rwlock' is NULL this function has no
 *    effect.
 *
 ***/
void silc_rwlock_unlock(SilcRwLock rwlock);

#endif
