new mutex and recmutex implementation (breaks sync.hpp for now)
prepares that chained sections if different kinds can be mixed makes recmutexes typesafe improves nobug tracking
This commit is contained in:
parent
59de53b25a
commit
a115759128
10 changed files with 343 additions and 190 deletions
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
PSplay lumiera_interfaceregistry;
|
||||
PSplay lumiera_pluginregistry;
|
||||
lumiera_mutex lumiera_interface_mutex;
|
||||
lumiera_recmutex lumiera_interface_mutex;
|
||||
|
||||
static int
|
||||
lumiera_interface_cmp_fn (const void* keya, const void* keyb);
|
||||
|
|
@ -126,7 +126,7 @@ lumiera_interfaceregistry_destroy (void)
|
|||
psplay_delete (lumiera_pluginregistry);
|
||||
lumiera_pluginregistry = NULL;
|
||||
|
||||
lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg));
|
||||
lumiera_recmutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg));
|
||||
|
||||
REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown");
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
//NOBUG_DECLARE_FLAG (interface);
|
||||
|
||||
extern PSplay lumiera_interfaceregistry;
|
||||
extern lumiera_mutex lumiera_interface_mutex;
|
||||
extern lumiera_recmutex lumiera_interface_mutex;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -75,8 +75,6 @@ struct lumiera_interfacenode_struct
|
|||
LumieraInterfacenode* deps;
|
||||
};
|
||||
|
||||
extern lumiera_mutex lumiera_interface_mutex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the interface registry
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ liblumiera_la_SOURCES = \
|
|||
$(liblumiera_la_srcdir)/error.c \
|
||||
$(liblumiera_la_srcdir)/exception.cpp \
|
||||
$(liblumiera_la_srcdir)/mutex.c \
|
||||
$(liblumiera_la_srcdir)/recmutex.c \
|
||||
$(liblumiera_la_srcdir)/rwlock.c \
|
||||
$(liblumiera_la_srcdir)/condition.c \
|
||||
$(liblumiera_la_srcdir)/reccondition.c \
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@
|
|||
* Mutual exclusion locking.
|
||||
*/
|
||||
|
||||
LUMIERA_ERROR_DEFINE (MUTEX_LOCK, "Mutex locking failed");
|
||||
LUMIERA_ERROR_DEFINE (MUTEX_UNLOCK, "Mutex unlocking failed");
|
||||
LUMIERA_ERROR_DEFINE (MUTEX_DESTROY, "Mutex destroy failed");
|
||||
LUMIERA_ERROR_DEFINE (LOCK_ACQUIRE, "locking failed");
|
||||
LUMIERA_ERROR_DEFINE (LOCK_RELEASE, "unlocking failed");
|
||||
LUMIERA_ERROR_DEFINE (LOCK_DESTROY, "lock destroy failed");
|
||||
|
||||
|
||||
LumieraMutex
|
||||
|
|
@ -44,32 +44,6 @@ lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* f
|
|||
}
|
||||
|
||||
|
||||
static pthread_once_t recursive_mutexattr_once = PTHREAD_ONCE_INIT;
|
||||
static pthread_mutexattr_t recursive_mutexattr;
|
||||
|
||||
static void recursive_mutexattr_init()
|
||||
{
|
||||
pthread_mutexattr_init (&recursive_mutexattr);
|
||||
pthread_mutexattr_settype (&recursive_mutexattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
|
||||
LumieraMutex
|
||||
lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
if (recursive_mutexattr_once == PTHREAD_ONCE_INIT)
|
||||
pthread_once (&recursive_mutexattr_once, recursive_mutexattr_init);
|
||||
|
||||
pthread_mutex_init (&self->mutex, &recursive_mutexattr);
|
||||
NOBUG_RESOURCE_HANDLE_INIT (self->rh);
|
||||
NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "recmutex", purpose, self, self->rh);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
LumieraMutex
|
||||
lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag)
|
||||
{
|
||||
|
|
@ -77,11 +51,16 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag)
|
|||
{
|
||||
NOBUG_RESOURCE_FORGET_RAW (flag, self->rh);
|
||||
if (pthread_mutex_destroy (&self->mutex))
|
||||
LUMIERA_DIE (MUTEX_DESTROY);
|
||||
LUMIERA_DIE (LOCK_DESTROY);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
int lumiera_mutex_unlock_cb (void* mutex)
|
||||
{
|
||||
return pthread_mutex_unlock ((pthread_mutex_t*) mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
|
|
|
|||
244
src/lib/mutex.h
244
src/lib/mutex.h
|
|
@ -23,6 +23,7 @@
|
|||
#define LUMIERA_MUTEX_H
|
||||
|
||||
#include "lib/error.h"
|
||||
#include "lib/sectionlock.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <nobug.h>
|
||||
|
|
@ -32,35 +33,30 @@
|
|||
* Mutual exclusion locking, header.
|
||||
*/
|
||||
|
||||
LUMIERA_ERROR_DECLARE (MUTEX_LOCK);
|
||||
LUMIERA_ERROR_DECLARE (MUTEX_UNLOCK);
|
||||
LUMIERA_ERROR_DECLARE (MUTEX_DESTROY);
|
||||
|
||||
/**
|
||||
* Mutual exclusive section.
|
||||
*/
|
||||
#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \
|
||||
= {(LumieraMutex)1 NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
|
||||
lumiera_lock_section_ = { \
|
||||
(void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_lock_section_.lock;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_lock_section_.lock = &(mtx)->mutex; \
|
||||
NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \
|
||||
NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \
|
||||
if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \
|
||||
RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \
|
||||
}); \
|
||||
lumiera_lock_section_.lock; \
|
||||
({ \
|
||||
LUMIERA_MUTEX_SECTION_UNLOCK; \
|
||||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Mutual exclusion chainbuilder section.
|
||||
* Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_MUTEX_SECTION_CHAIN(b){run();}}
|
||||
|
|
@ -68,99 +64,81 @@ LUMIERA_ERROR_DECLARE (MUTEX_DESTROY);
|
|||
* This macro should only be used inside LUMIERA_MUTEX_SECTION and should be
|
||||
* called on the correct mutexes, period.
|
||||
*/
|
||||
#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \
|
||||
NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \
|
||||
NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_EXCLUSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
if (lumiera_mutex_section_old_->mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \
|
||||
lumiera_mutex_section_old_->mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \
|
||||
} \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
|
||||
#define LUMIERA_MUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \
|
||||
NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \
|
||||
(void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_lock_section_.lock;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_lock_section_.lock = &(mtx)->mutex; \
|
||||
NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire mutex", &lumiera_lock_section_, \
|
||||
NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \
|
||||
if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \
|
||||
RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \
|
||||
LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \
|
||||
}); \
|
||||
lumiera_lock_section_.lock; \
|
||||
({ \
|
||||
LUMIERA_MUTEX_SECTION_UNLOCK; \
|
||||
}))
|
||||
|
||||
|
||||
#define LUMIERA_MUTEX_SECTION_UNLOCK \
|
||||
LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_)
|
||||
|
||||
|
||||
/**
|
||||
* Recursive Mutual exclusive section.
|
||||
*/
|
||||
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ \
|
||||
= {(LumieraMutex)1 NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \
|
||||
for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
|
||||
lumiera_lock_section_ = { \
|
||||
(void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_lock_section_.lock;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_lock_section_.lock = &(mtx)->recmutex; \
|
||||
NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \
|
||||
NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \
|
||||
if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \
|
||||
RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \
|
||||
}); \
|
||||
lumiera_lock_section_.lock; \
|
||||
({ \
|
||||
LUMIERA_MUTEX_SECTION_UNLOCK; \
|
||||
}))
|
||||
|
||||
|
||||
/**
|
||||
* Mutual exclusion chainbuilder section.
|
||||
* Usage: LUMIERA_MUTEX_SECTION(a){LUMIERA_RECMUTEX_SECTION_CHAIN(b){run();}}
|
||||
* calls lock(a); lock(b); unlock(a); run(); unlock(b);
|
||||
* This macro should only be used inside LUMIERA_MUTEX_SECTION and should be
|
||||
* called on the correct mutexes, period.
|
||||
*/
|
||||
#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_mutexacquirer *lumiera_mutex_section_old_ = &lumiera_mutex_section_, \
|
||||
NOBUG_CLEANUP(lumiera_mutexacquirer_ensureunlocked) lumiera_mutex_section_ = {(LumieraMutex)1 \
|
||||
NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_mutex_section_.mutex;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_mutex_section_.mutex = (mtx); \
|
||||
NOBUG_RESOURCE_HANDLE_INIT (lumiera_mutex_section_.rh); \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_mutex_section_, \
|
||||
NOBUG_RESOURCE_RECURSIVE, lumiera_mutex_section_.rh); \
|
||||
if (pthread_mutex_lock (&(mtx)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
|
||||
if (lumiera_mutex_section_old_->mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_old_->mutex->mutex); \
|
||||
lumiera_mutex_section_old_->mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_old_->rh); \
|
||||
} \
|
||||
}); \
|
||||
lumiera_mutex_section_.mutex; \
|
||||
({ \
|
||||
if (lumiera_mutex_section_.mutex) \
|
||||
{ \
|
||||
pthread_mutex_unlock (&lumiera_mutex_section_.mutex->mutex); \
|
||||
lumiera_mutex_section_.mutex = NULL; \
|
||||
RESOURCE_LEAVE(nobugflag, lumiera_mutex_section_.rh); \
|
||||
} \
|
||||
#define LUMIERA_RECMUTEX_SECTION_CHAIN(nobugflag, mtx) \
|
||||
for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \
|
||||
NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \
|
||||
(void*)1, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
|
||||
lumiera_lock_section_.lock;) \
|
||||
for ( \
|
||||
({ \
|
||||
lumiera_lock_section_.lock = &(mtx)->recmutex; \
|
||||
NOBUG_IF_ALPHA(lumiera_lock_section_.flag = &NOBUG_FLAG(nobugflag);) \
|
||||
RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", &lumiera_lock_section_, \
|
||||
NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \
|
||||
if (pthread_mutex_lock (lumiera_lock_section_.lock)) LUMIERA_DIE (LOCK_ACQUIRE); \
|
||||
RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_recursive, lumiera_lock_section_.rh); \
|
||||
LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_) \
|
||||
}); \
|
||||
lumiera_lock_section_.lock; \
|
||||
({ \
|
||||
LUMIERA_MUTEX_SECTION_UNLOCK; \
|
||||
}))
|
||||
|
||||
|
||||
#define LUMIERA_RECMUTEX_SECTION_UNLOCK \
|
||||
LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mutex.
|
||||
*
|
||||
|
|
@ -173,6 +151,14 @@ struct lumiera_mutex_struct
|
|||
typedef struct lumiera_mutex_struct lumiera_mutex;
|
||||
typedef lumiera_mutex* LumieraMutex;
|
||||
|
||||
struct lumiera_recmutex_struct
|
||||
{
|
||||
pthread_mutex_t recmutex;
|
||||
RESOURCE_HANDLE (rh);
|
||||
};
|
||||
typedef struct lumiera_recmutex_struct lumiera_recmutex;
|
||||
typedef lumiera_recmutex* LumieraRecMutex;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a mutex variable
|
||||
|
|
@ -183,16 +169,6 @@ typedef lumiera_mutex* LumieraMutex;
|
|||
LumieraMutex
|
||||
lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag);
|
||||
|
||||
/**
|
||||
* Initialize a mutex variable
|
||||
* Initializes a 'recursive' mutex which might be locked by the same thread multiple times.
|
||||
* @param self is a pointer to the mutex to be initialized
|
||||
* @return self as given
|
||||
*/
|
||||
LumieraMutex
|
||||
lumiera_recmutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag);
|
||||
|
||||
|
||||
/**
|
||||
* Destroy a mutex variable
|
||||
* @param self is a pointer to the mutex to be destroyed
|
||||
|
|
@ -202,23 +178,31 @@ LumieraMutex
|
|||
lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag);
|
||||
|
||||
|
||||
/**
|
||||
* mutexacquirer used to manage the state of a mutex.
|
||||
*/
|
||||
struct lumiera_mutexacquirer_struct
|
||||
{
|
||||
LumieraMutex mutex;
|
||||
RESOURCE_HANDLE (rh);
|
||||
};
|
||||
typedef struct lumiera_mutexacquirer_struct lumiera_mutexacquirer;
|
||||
typedef struct lumiera_mutexacquirer_struct* LumieraMutexacquirer;
|
||||
|
||||
/* helper function for nobug */
|
||||
static inline void
|
||||
lumiera_mutexacquirer_ensureunlocked (LumieraMutexacquirer self)
|
||||
{
|
||||
ENSURE (!self->mutex, "forgot to unlock mutex");
|
||||
}
|
||||
/**
|
||||
* Initialize a recursive mutex variable
|
||||
* Initializes a 'recursive' mutex which might be locked by the same thread multiple times.
|
||||
* @param self is a pointer to the mutex to be initialized
|
||||
* @return self as given
|
||||
*/
|
||||
LumieraRecMutex
|
||||
lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag);
|
||||
|
||||
/**
|
||||
* Destroy a recursive mutex variable
|
||||
* @param self is a pointer to the mutex to be destroyed
|
||||
* @return self as given
|
||||
*/
|
||||
LumieraRecMutex
|
||||
lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag);
|
||||
|
||||
/**
|
||||
* Callback for unlocking mutexes.
|
||||
* @internal
|
||||
*/
|
||||
int
|
||||
lumiera_mutex_unlock_cb (void* mutex);
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
|
|
|
|||
74
src/lib/recmutex.c
Normal file
74
src/lib/recmutex.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
recmutex.c - recursive mutex
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 2009, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "lib/mutex.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Recursive Mutexes.
|
||||
*/
|
||||
|
||||
|
||||
static pthread_once_t recmutexattr_once = PTHREAD_ONCE_INIT;
|
||||
static pthread_mutexattr_t recmutexattr;
|
||||
|
||||
static void recmutexattr_init()
|
||||
{
|
||||
pthread_mutexattr_init (&recmutexattr);
|
||||
pthread_mutexattr_settype (&recmutexattr, PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
|
||||
LumieraRecMutex
|
||||
lumiera_recmutex_init (LumieraRecMutex self, const char* purpose, struct nobug_flag* flag)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
if (recmutexattr_once == PTHREAD_ONCE_INIT)
|
||||
pthread_once (&recmutexattr_once, recmutexattr_init);
|
||||
|
||||
pthread_mutex_init (&self->recmutex, &recmutexattr);
|
||||
NOBUG_RESOURCE_HANDLE_INIT (self->rh);
|
||||
NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "recmutex", purpose, self, self->rh);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
LumieraRecMutex
|
||||
lumiera_recmutex_destroy (LumieraRecMutex self, struct nobug_flag* flag)
|
||||
{
|
||||
if (self)
|
||||
{
|
||||
NOBUG_RESOURCE_FORGET_RAW (flag, self->rh);
|
||||
if (pthread_mutex_destroy (&self->recmutex))
|
||||
LUMIERA_DIE (LOCK_DESTROY);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
83
src/lib/sectionlock.h
Normal file
83
src/lib/sectionlock.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
sectionlock.h - mutex state handle
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Christian Thaeter <ct@pipapo.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef LUMIERA_SECTIONLOCK_H
|
||||
#define LUMIERA_SECTIONLOCK_H
|
||||
|
||||
#include "lib/error.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <nobug.h>
|
||||
|
||||
LUMIERA_ERROR_DECLARE (LOCK_ACQUIRE);
|
||||
LUMIERA_ERROR_DECLARE (LOCK_RELEASE);
|
||||
LUMIERA_ERROR_DECLARE (LOCK_DESTROY);
|
||||
|
||||
|
||||
typedef int (*lumiera_sectionlock_unlock_fn)(void*);
|
||||
|
||||
/**
|
||||
* sectionlock used to manage the state of mutexes.
|
||||
*/
|
||||
struct lumiera_sectionlock_struct
|
||||
{
|
||||
void* lock;
|
||||
lumiera_sectionlock_unlock_fn unlock;
|
||||
NOBUG_IF_ALPHA(struct nobug_flag* flag);
|
||||
RESOURCE_HANDLE (rh);
|
||||
};
|
||||
typedef struct lumiera_sectionlock_struct lumiera_sectionlock;
|
||||
typedef struct lumiera_sectionlock_struct* LumieraSectionlock;
|
||||
|
||||
/* helper function for nobug */
|
||||
static inline void
|
||||
lumiera_sectionlock_ensureunlocked (LumieraSectionlock self)
|
||||
{
|
||||
ENSURE (!self->lock, "forgot to unlock");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Unlock the lock hold in a SECTION
|
||||
* @internal
|
||||
* @param sectionname name used for the sectionlock instance
|
||||
* @param ... some extra code to execute
|
||||
*/
|
||||
#define LUMIERA_SECTION_UNLOCK_(section, ...) \
|
||||
do if ((section)->lock) \
|
||||
{ \
|
||||
if ((section)->unlock((section)->lock)) \
|
||||
LUMIERA_DIE (LOCK_RELEASE); \
|
||||
(section)->lock = NULL; \
|
||||
__VA_ARGS__; \
|
||||
NOBUG_RESOURCE_LEAVE_RAW((section)->flag, (section)->rh); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
@ -102,21 +102,21 @@ namespace lib {
|
|||
//------------------Resource-Tracking------
|
||||
void __may_block() { TODO ("Record we may block on mutex"); }
|
||||
void __enter() { TODO ("Record we successfully acquired the mutex"); }
|
||||
void __leave() { TODO ("Record we are releasing the mutex"); }
|
||||
void __left() { TODO ("Record we are released the mutex"); }
|
||||
};
|
||||
|
||||
|
||||
struct Wrapped_LumieraRecMutex
|
||||
: public lumiera_mutex
|
||||
: public lumiera_recmutex
|
||||
{
|
||||
protected:
|
||||
Wrapped_LumieraRecMutex() { lumiera_recmutex_init (this, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync)); }
|
||||
~Wrapped_LumieraRecMutex() { lumiera_mutex_destroy (this, &NOBUG_FLAG(sync)); }
|
||||
~Wrapped_LumieraRecMutex() { lumiera_recmutex_destroy (this, &NOBUG_FLAG(sync)); }
|
||||
|
||||
//------------------Resource-Tracking------
|
||||
void __may_block() { TODO ("Record we may block on mutex"); }
|
||||
void __enter() { TODO ("Record we successfully acquired the mutex"); }
|
||||
void __leave() { TODO ("Record we are releasing the mutex"); }
|
||||
void __left() { TODO ("Record we are released the mutex"); }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ namespace lib {
|
|||
//------------------Resource-Tracking------
|
||||
void __may_block() { TODO ("Record we may block on mutex"); }
|
||||
void __enter() { TODO ("Record we successfully acquired the mutex"); }
|
||||
void __leave() { TODO ("Record we are releasing the mutex"); }
|
||||
void __left() { TODO ("Record we are released the mutex"); }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -144,7 +144,7 @@ namespace lib {
|
|||
//------------------Resource-Tracking------
|
||||
void __may_block() { TODO ("Record we may block on mutex"); }
|
||||
void __enter() { TODO ("Record we successfully acquired the mutex"); }
|
||||
void __leave() { TODO ("Record we are releasing the mutex"); }
|
||||
void __left() { TODO ("Record we are released the mutex"); }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -156,10 +156,10 @@ namespace lib {
|
|||
: protected MTX
|
||||
{
|
||||
protected:
|
||||
using MTX::mutex;
|
||||
//using MTX::mutex;
|
||||
using MTX::__may_block;
|
||||
using MTX::__enter;
|
||||
using MTX::__leave;
|
||||
using MTX::__left;
|
||||
|
||||
~Mutex () { }
|
||||
Mutex () { }
|
||||
|
|
@ -171,19 +171,22 @@ namespace lib {
|
|||
acquire()
|
||||
{
|
||||
__may_block();
|
||||
|
||||
if (pthread_mutex_lock (&mutex))
|
||||
throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code
|
||||
|
||||
|
||||
FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh");
|
||||
// well .. specialization on the mutex type shall solve it ...
|
||||
//if (pthread_mutex_lock (&mutex))
|
||||
// throw lumiera::error::State("Mutex acquire failed."); ///////TODO capture the error-code
|
||||
|
||||
__enter();
|
||||
}
|
||||
|
||||
void
|
||||
release()
|
||||
{
|
||||
__leave();
|
||||
|
||||
pthread_mutex_unlock (&mutex);
|
||||
{
|
||||
FIXME ("For to make C typesafe we have now mutex and recmutex member gnah :P -- cehteh");
|
||||
//pthread_mutex_unlock (&mutex);
|
||||
|
||||
__left();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -436,3 +439,10 @@ namespace lib {
|
|||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-file-style: "gnu"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ TEST "mutex not unlocked asserts" mutexforgotunlock <<END
|
|||
return: 134
|
||||
END
|
||||
|
||||
TEST "mutex explicitly unlocked" mutexexplicitunlock <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "nested mutex section" nestedmutexsection <<END
|
||||
out: outer mutex locked section
|
||||
|
|
@ -25,8 +29,8 @@ END
|
|||
|
||||
|
||||
TEST "recursive mutex section" recursivemutexsection <<END
|
||||
out: mutex locked once
|
||||
out: mutex locked twice
|
||||
out: recmutex locked once
|
||||
out: recmutex locked twice
|
||||
END
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,22 @@ TEST ("mutexforgotunlock")
|
|||
}
|
||||
|
||||
|
||||
TEST ("mutexexplicitunlock")
|
||||
{
|
||||
lumiera_mutex m;
|
||||
lumiera_mutex_init (&m, "mutexforgotunlock", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
ECHO("mutex locked section");
|
||||
LUMIERA_MUTEX_SECTION_UNLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
|
||||
TEST ("nestedmutexsection")
|
||||
{
|
||||
lumiera_mutex m;
|
||||
|
|
@ -107,25 +123,29 @@ TEST ("chainedmutexsection")
|
|||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST ("recursivemutexsection")
|
||||
{
|
||||
lumiera_mutex m;
|
||||
lumiera_recmutex_init (&m, "m_mutexsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_recmutex m;
|
||||
lumiera_recmutex_init (&m, "m_recmutexsection", &NOBUG_FLAG(NOBUG_ON));
|
||||
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
LUMIERA_RECMUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
printf ("mutex locked once\n");
|
||||
printf ("recmutex locked once\n");
|
||||
|
||||
LUMIERA_MUTEX_SECTION (NOBUG_ON, &m)
|
||||
LUMIERA_RECMUTEX_SECTION (NOBUG_ON, &m)
|
||||
{
|
||||
printf ("mutex locked twice\n");
|
||||
printf ("recmutex locked twice\n");
|
||||
}
|
||||
}
|
||||
|
||||
lumiera_mutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
lumiera_recmutex_destroy (&m, &NOBUG_FLAG(NOBUG_ON));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST ("rwlocksection")
|
||||
{
|
||||
lumiera_rwlock rwlock;
|
||||
|
|
|
|||
Loading…
Reference in a new issue