diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index b6f89847b..eb1a20548 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -25,6 +25,7 @@ liblumiera_la_SOURCES = \ $(liblumiera_la_srcdir)/error.c \ $(liblumiera_la_srcdir)/mpool.c \ $(liblumiera_la_srcdir)/exception.cpp \ + $(liblumiera_la_srcdir)/lockerror.c \ $(liblumiera_la_srcdir)/mutex.c \ $(liblumiera_la_srcdir)/recmutex.c \ $(liblumiera_la_srcdir)/rwlock.c \ @@ -54,6 +55,7 @@ noinst_HEADERS += \ $(liblumiera_la_srcdir)/error.h \ $(liblumiera_la_srcdir)/error.hpp \ $(liblumiera_la_srcdir)/mpool.h \ + $(liblumiera_la_srcdir)/lockerror.h \ $(liblumiera_la_srcdir)/mutex.h \ $(liblumiera_la_srcdir)/recmutex.h \ $(liblumiera_la_srcdir)/rwlock.h \ diff --git a/src/lib/condition.c b/src/lib/condition.c index 9db79c54f..432ba52c9 100644 --- a/src/lib/condition.c +++ b/src/lib/condition.c @@ -2,7 +2,7 @@ condition.c - condition variable Copyright (C) Lumiera.org - 2008, 2009 Christian Thaeter + 2008, 2009, 2010, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -58,11 +58,10 @@ lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag) } - -int lumiera_condition_unlock_cb (void* cond) -{ - return pthread_mutex_unlock (&((LumieraCondition)cond)->cndmutex); -} - - - +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/condition.h b/src/lib/condition.h index 29db12edb..293d0143e 100644 --- a/src/lib/condition.h +++ b/src/lib/condition.h @@ -2,7 +2,7 @@ condition.h - condition variables Copyright (C) Lumiera.org - 2008, Christian Thaeter + 2008, 2010, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -24,8 +24,11 @@ #include "lib/error.h" #include "lib/sectionlock.h" +#include "lib/lockerror.h" #include +#include +#include #include /** @@ -43,49 +46,42 @@ * @param nobugflag NoBug flag used to log actions on the condition * @param cnd Condition variable to be locked */ -#define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_cond_section_ = { \ - cnd, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_cond_section_.lock) \ - { \ - RESOURCE_WAIT (nobugflag, (cnd)->rh, "acquire condmutex", lumiera_cond_section_.rh); \ - if (pthread_mutex_lock (&(cnd)->cndmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ - } \ - lumiera_cond_section_.lock; \ - }); \ - ({ \ - LUMIERA_CONDITION_SECTION_UNLOCK; \ +#define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + cnd, (lumiera_sectionlock_unlock_fn) lumiera_condition_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + lumiera_lock_section_.lock = \ + lumiera_condition_lock (cnd, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + }); \ + ({ \ + LUMIERA_CONDITION_SECTION_UNLOCK; \ })) -#define LUMIERA_CONDITION_SECTION_CHAIN(nobugflag, cnd) \ - for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_cond_section_ = { \ - cnd, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_cond_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condmutex", lumiera_cond_section_.rh); \ - if (pthread_mutex_lock (&(cnd)->cndmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ - LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ - } \ - lumiera_cond_section_.lock; \ - }); \ - ({ \ - LUMIERA_CONDITION_SECTION_UNLOCK; \ +#define LUMIERA_CONDITION_SECTION_CHAIN(nobugflag, cnd) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + cnd, (lumiera_sectionlock_unlock_fn) lumiera_condition_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_condition_lock (cnd, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + } \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_CONDITION_SECTION_UNLOCK; \ })) - #define LUMIERA_CONDITION_SECTION_UNLOCK \ - LUMIERA_SECTION_UNLOCK_(&lumiera_cond_section_) + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) /** @@ -93,13 +89,30 @@ * Must be used inside a CONDITION_SECTION. * @param expr Conditon which must become true, else the condition variable goes back into sleep */ -#define LUMIERA_CONDITION_WAIT(expr) \ - do { \ - REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_cond_section_.flag, NOBUG_RESOURCE_WAITING, lumiera_cond_section_.rh); \ - pthread_cond_wait (&((LumieraCondition)lumiera_cond_section_.lock)->cond, \ - &((LumieraCondition)lumiera_cond_section_.lock)->cndmutex); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_cond_section_.flag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_cond_section_.rh); \ +#define LUMIERA_CONDITION_WAIT(expr) \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Condition mutex not locked"); \ + lumiera_condition_wait (lumiera_lock_section_.lock, \ + lumiera_lock_section_.flag, \ + &lumiera_lock_section_.rh); \ + } while (!(expr)) + + +/** + * Timed wait for a condition. + * Must be used inside a CONDITION_SECTION. + * @param expr Conditon which must become true, else the condition variable goes back into sleep + * @param timeout time when the wait expired + * sets LUMIERA_ERROR_LOCK_TIMEOUT when the timeout passed + */ +#define LUMIERA_CONDITION_TIMEDWAIT(expr, timeout) \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Condition mutex not locked"); \ + if (!lumiera_condition_timedwait (lumiera_lock_section_.lock, \ + timeout, \ + lumiera_lock_section_.flag, \ + &lumiera_lock_section_.rh)) \ + break; \ } while (!(expr)) @@ -108,11 +121,11 @@ * Must be used inside a CONDITION_SECTION. * Wakes one thread waiting on the condition variable */ -#define LUMIERA_CONDITION_SIGNAL \ - do { \ - REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ - TRACE(NOBUG_FLAG_RAW(lumiera_cond_section_.flag), "Signal %p", &lumiera_cond_section_); \ - pthread_cond_signal (&((LumieraCondition)lumiera_cond_section_.lock)->cond); \ +#define LUMIERA_CONDITION_SIGNAL \ + do { \ + REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ + lumiera_condition_signal (lumiera_lock_section_.lock, \ + lumiera_lock_section_.flag); \ } while (0) @@ -121,11 +134,11 @@ * Must be used inside a CONDITION_SECTION. * Wakes all threads waiting on the condition variable */ -#define LUMIERA_CONDITION_BROADCAST \ - do { \ - REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ - TRACE(NOBUG_FLAG_RAW(lumiera_cond_section_.flag), "Broadcast %p", &lumiera_cond_section_); \ - pthread_cond_broadcast (&((LumieraCondition)lumiera_cond_section_.lock)->cond); \ +#define LUMIERA_CONDITION_BROADCAST \ + do { \ + REQUIRE (lumiera_cond_section_.lock, "Condition mutex not locked"); \ + lumiera_condition_broadcast (lumiera_lock_section_.lock, \ + lumiera_lock_section_.flag); \ } while (0) @@ -160,8 +173,148 @@ lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug LumieraCondition lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag); -int -lumiera_condition_unlock_cb (void* cond); + +static inline LumieraCondition +lumiera_condition_lock (LumieraCondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire condvar", *handle); + + if (pthread_mutex_lock (&self->cndmutex)) + LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */ + + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + + return self; +} + + +static inline LumieraCondition +lumiera_condition_trylock (LumieraCondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire condvar", *handle); + + int err = pthread_mutex_trylock (&self->cndmutex); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraCondition +lumiera_condition_timedlock (LumieraCondition self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire condvar", *handle); + + int err = pthread_mutex_timedlock (&self->cndmutex, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraCondition +lumiera_condition_wait (LumieraCondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_WAITING, *handle); + + pthread_cond_wait (&self->cond, &self->cndmutex); + + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + return self; +} + + +static inline LumieraCondition +lumiera_condition_timedwait (LumieraCondition self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_WAITING, *handle); + + int err; + do { + err = pthread_cond_timedwait (&self->cond, &self->cndmutex, timeout); + } while(err == EINTR); + + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_EXCLUSIVE, *handle); + + if (err) + { + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + + +static inline void +lumiera_condition_signal (LumieraCondition self, struct nobug_flag* flag) +{ + TRACE(NOBUG_FLAG_RAW(flag), "Signal %p", self); + pthread_cond_signal (&self->cond); +} + + +static inline void +lumiera_condition_broadcast (LumieraCondition self, struct nobug_flag* flag) +{ + TRACE(NOBUG_FLAG_RAW(flag), "Broadcast %p", self); + pthread_cond_broadcast (&self->cond); +} + + +static inline void +lumiera_condition_unlock (LumieraCondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + REQUIRE(self); + + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) + { + if (pthread_mutex_unlock (&self->cndmutex)) + LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */ + } +} #endif diff --git a/src/lib/error.c b/src/lib/error.c index caf2cf81b..840288c8d 100644 --- a/src/lib/error.c +++ b/src/lib/error.c @@ -34,6 +34,7 @@ */ LUMIERA_ERROR_DEFINE (ERRNO, "errno"); LUMIERA_ERROR_DEFINE (EERROR, "could not initialize error system"); +LUMIERA_ERROR_DEFINE (UNKNOWN, "unknown error"); /* Thread local storage */ diff --git a/src/lib/error.h b/src/lib/error.h index 100ad7c7b..308adf480 100644 --- a/src/lib/error.h +++ b/src/lib/error.h @@ -164,6 +164,7 @@ lumiera_error_peek (void); predefined errors */ LUMIERA_ERROR_DECLARE (ERRNO); +LUMIERA_ERROR_DECLARE (UNKNOWN); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/lib/lockerror.c b/src/lib/lockerror.c new file mode 100644 index 000000000..6c53b8fbb --- /dev/null +++ b/src/lib/lockerror.c @@ -0,0 +1,79 @@ +/* + lockerror.c - error declarations for all locks (mutex, rwlocks, cond vars) + + Copyright (C) Lumiera.org + 2010, Christian Thaeter + + 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/lockerror.h" + +#include + +/* fatal errors (EINVAL usually) */ +LUMIERA_ERROR_DEFINE (LOCK_ACQUIRE, "locking failed"); +LUMIERA_ERROR_DEFINE (LOCK_RELEASE, "unlocking failed"); +LUMIERA_ERROR_DEFINE (LOCK_DESTROY, "lock destroy failed"); + +/* runtime errors */ +LUMIERA_ERROR_DEFINE (LOCK_INVAL, "lock initialization error"); +LUMIERA_ERROR_DEFINE (LOCK_BUSY, "already locked"); +LUMIERA_ERROR_DEFINE (LOCK_DEADLK, "already locked by this thread"); +LUMIERA_ERROR_DEFINE (LOCK_PERM, "not locked by this thread"); +LUMIERA_ERROR_DEFINE (LOCK_TIMEOUT, "timeout"); +LUMIERA_ERROR_DEFINE (LOCK_AGAIN, "too much recursive locks"); + + + +void +lumiera_lockerror_set (int err, struct nobug_flag* flag, const char* extra) +{ + switch (err) + { + case 0: + break; + case EINVAL: + LUMIERA_ERROR_SET_ALERT(NOBUG_FLAG_RAW(flag), LOCK_INVAL, extra); + break; + case EBUSY: + LUMIERA_ERROR_SET(NOBUG_FLAG_RAW(flag), LOCK_BUSY, extra); + break; + case EDEADLK: + LUMIERA_ERROR_SET(NOBUG_FLAG_RAW(flag), LOCK_DEADLK, extra); + break; + case EPERM: + LUMIERA_ERROR_SET_ALERT(NOBUG_FLAG_RAW(flag), LOCK_PERM, extra); + break; + case ETIMEDOUT: + LUMIERA_ERROR_SET(NOBUG_FLAG_RAW(flag), LOCK_TIMEOUT, extra); + break; + case EAGAIN: + LUMIERA_ERROR_SET_WARNING(NOBUG_FLAG_RAW(flag), LOCK_AGAIN, extra); + break; + default: + LUMIERA_ERROR_SET_CRITICAL(NOBUG_FLAG_RAW(flag), UNKNOWN, extra); + break; + } +} + + +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/lockerror.h b/src/lib/lockerror.h new file mode 100644 index 000000000..4916d8a57 --- /dev/null +++ b/src/lib/lockerror.h @@ -0,0 +1,53 @@ +/* + lockerror.h - error declarations for all locks (mutex, rwlocks, cond vars) + + Copyright (C) Lumiera.org + 2010, Christian Thaeter + + 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_LOCKERRORS_H +#define LUMIERA_LOCKERRORS_H + +#include "lib/error.h" + +/* fatal errors (EINVAL usually), we DIE on these, shall never ever happen on a correct program */ +LUMIERA_ERROR_DECLARE (LOCK_ACQUIRE); +LUMIERA_ERROR_DECLARE (LOCK_RELEASE); +LUMIERA_ERROR_DECLARE (LOCK_DESTROY); + +/* runtime errors */ +LUMIERA_ERROR_DECLARE (LOCK_INVAL); +LUMIERA_ERROR_DECLARE (LOCK_BUSY); +LUMIERA_ERROR_DECLARE (LOCK_DEADLK); +LUMIERA_ERROR_DECLARE (LOCK_PERM); +LUMIERA_ERROR_DECLARE (LOCK_TIMEOUT); +LUMIERA_ERROR_DECLARE (LOCK_AGAIN); + +/** + * Translate pthread error code into lumiera error + */ +void +lumiera_lockerror_set (int err, struct nobug_flag* flag, const char* extra); + +#endif +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/mutex.c b/src/lib/mutex.c index 25b56679c..bdbc6662e 100644 --- a/src/lib/mutex.c +++ b/src/lib/mutex.c @@ -26,11 +26,6 @@ * Mutual exclusion locking. */ -LUMIERA_ERROR_DEFINE (LOCK_ACQUIRE, "locking failed"); -LUMIERA_ERROR_DEFINE (LOCK_RELEASE, "unlocking failed"); -LUMIERA_ERROR_DEFINE (LOCK_DESTROY, "lock destroy failed"); - - LumieraMutex lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* flag) { @@ -56,10 +51,7 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag) return self; } -int lumiera_mutex_unlock_cb (void* mutex) -{ - return pthread_mutex_unlock (&((LumieraMutex)mutex)->mutex); -} + /* // Local Variables: diff --git a/src/lib/mutex.h b/src/lib/mutex.h index c49265e6a..04a859b91 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -24,8 +24,10 @@ #include "lib/error.h" #include "lib/sectionlock.h" +#include "lib/lockerror.h" #include +#include #include /** @@ -33,26 +35,22 @@ * Mutual exclusion locking, header. */ - /** * Mutual exclusive section. */ -#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_lock_section_ = { \ - mtx, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - RESOURCE_WAIT (nobugflag, (mtx)->rh, "acquire mutex", lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ - } \ - lumiera_lock_section_.lock; \ - }); \ - ({ \ - LUMIERA_MUTEX_SECTION_UNLOCK; \ +#define LUMIERA_MUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + lumiera_lock_section_.lock = \ + lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_MUTEX_SECTION_UNLOCK; \ })) @@ -63,26 +61,26 @@ * 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_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ - mtx, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_WAIT (nobugflag, (mtx)->rh, "acquire mutex", lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->mutex)) \ - 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_CHAIN(nobugflag, mtx) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_mutex_lock (mtx, &NOBUG_FLAG(nobugflag), &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_) @@ -104,6 +102,8 @@ typedef lumiera_mutex* LumieraMutex; * Initialize a mutex variable * This initializes a 'fast' default mutex which must not be locked recursively from one thread. * @param self is a pointer to the mutex to be initialized + * @param purpose textual hint for the nobug resourcetracker + * @param flag nobug logging target * @return self as given */ LumieraMutex @@ -112,6 +112,7 @@ lumiera_mutex_init (LumieraMutex self, const char* purpose, struct nobug_flag* f /** * Destroy a mutex variable * @param self is a pointer to the mutex to be destroyed + * @param flag nobug logging target * @return self as given */ LumieraMutex @@ -119,11 +120,115 @@ lumiera_mutex_destroy (LumieraMutex self, struct nobug_flag* flag); /** - * Callback for unlocking mutexes. - * @internal + * Lock a mutex variable + * Never fails + * @param self is a pointer to the mutex to be destroyed + * @param flag nobug logging target + * @param handle pointer to nobug user handle (NULL in beta and release builds) + * @return self as given */ -int -lumiera_mutex_unlock_cb (void* mutex); +static inline LumieraMutex +lumiera_mutex_lock (LumieraMutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire mutex", *handle); + + if (pthread_mutex_lock (&self->mutex)) + LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */ + + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + + return self; +} + + +/** + * Try to lock a mutex variable + * @param self is a pointer to the mutex to be destroyed + * @param flag nobug logging target + * @param handle pointer to nobug user handle (NULL in beta and release builds) + * @return self as given or NULL on error, lumiera_error gets set approbiately + */ +static inline LumieraMutex +lumiera_mutex_trylock (LumieraMutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire mutex", *handle); + + int err = pthread_mutex_trylock (&self->mutex); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + +/** + * Try to lock a mutex variable with a timeout + * @param self is a pointer to the mutex to be destroyed + * @param timeout timeout for waiting for the lock + * @param flag nobug logging target + * @param handle pointer to nobug user handle (NULL in beta and release builds) + * @return self as given or NULL on error, lumiera_error gets set approbiately + */ +static inline LumieraMutex +lumiera_mutex_timedlock (LumieraMutex self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire mutex", *handle); + + int err = pthread_mutex_timedlock (&self->mutex, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +/** + * unlock a mutex variable + * Never fails + * @param self is a pointer to the mutex to be destroyed + * @param flag nobug logging target + * @param handle pointer to nobug user handle (NULL in beta and release builds) + */ +static inline void +lumiera_mutex_unlock (LumieraMutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + REQUIRE(self); + + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) + { + if (pthread_mutex_unlock (&self->mutex)) + LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */ + } +} #endif diff --git a/src/lib/reccondition.c b/src/lib/reccondition.c index 59bc956aa..bf9631ebb 100644 --- a/src/lib/reccondition.c +++ b/src/lib/reccondition.c @@ -72,9 +72,10 @@ lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag) } - -int lumiera_reccondition_unlock_cb (void* cond) -{ - return pthread_mutex_unlock (&((LumieraReccondition)cond)->reccndmutex); -} - +/* +// Local Variables: +// mode: C +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +*/ diff --git a/src/lib/reccondition.h b/src/lib/reccondition.h index fe619bf2d..fae19ea38 100644 --- a/src/lib/reccondition.h +++ b/src/lib/reccondition.h @@ -2,7 +2,7 @@ reccondition.h - recursive locked condition variables Copyright (C) Lumiera.org - 2008, 2009, Christian Thaeter + 2008, 2009, 2010, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -24,8 +24,11 @@ #include "lib/error.h" #include "lib/sectionlock.h" +#include "lib/lockerror.h" #include +#include +#include #include /** @@ -41,49 +44,43 @@ * @param nobugflag NoBug flag used to log actions on the condition * @param cnd Condition variable to be locked */ -#define LUMIERA_RECCONDITION_SECTION(nobugflag, cnd) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_reccond_section_ = { \ - cnd, lumiera_reccondition_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_reccond_section_.lock) \ - { \ - RESOURCE_WAIT (nobugflag, (cnd)->rh, "acquire reccondmutex", lumiera_reccond_section_.rh); \ - if (pthread_mutex_lock (&(cnd)->reccndmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ - } \ - lumiera_reccond_section_.lock; \ - }); \ - ({ \ - LUMIERA_RECCONDITION_SECTION_UNLOCK; \ +#define LUMIERA_RECCONDITION_SECTION(nobugflag, cnd) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + cnd, (lumiera_sectionlock_unlock_fn) lumiera_reccondition_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + lumiera_lock_section_.lock = \ + lumiera_reccondition_lock (cnd, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + }); \ + ({ \ + LUMIERA_RECCONDITION_SECTION_UNLOCK; \ })) -#define LUMIERA_RECCONDITION_SECTION_CHAIN(nobugflag, cnd) \ - for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_reccond_section_ = { \ - cnd, lumiera_reccondition_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_reccond_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_WAIT (nobugflag, (cnd)->rh, "acquire reccondmutex", lumiera_reccond_section_.rh); \ - if (pthread_mutex_lock (&(cnd)->reccndmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ - LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ - } \ - lumiera_reccond_section_.lock; \ - }); \ - ({ \ - LUMIERA_RECCONDITION_SECTION_UNLOCK; \ +#define LUMIERA_RECCONDITION_SECTION_CHAIN(nobugflag, cnd) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + cnd, (lumiera_sectionlock_unlock_fn) lumiera_reccondition_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_reccondition_lock (cnd, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + } \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RECCONDITION_SECTION_UNLOCK; \ })) #define LUMIERA_RECCONDITION_SECTION_UNLOCK \ - LUMIERA_SECTION_UNLOCK_(&lumiera_reccond_section_) + LUMIERA_SECTION_UNLOCK_(&lumiera_lock_section_) /** @@ -91,26 +88,45 @@ * Must be used inside a RECCONDITION_SECTION. * @param expr Condition which must become true, else the condition variable goes back into sleep */ -#define LUMIERA_RECCONDITION_WAIT(expr) \ - do { \ - REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_WAITING, lumiera_reccond_section_.rh); \ - pthread_cond_wait (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond, \ - &((LumieraReccondition)lumiera_reccond_section_.lock)->reccndmutex); \ - NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \ +#define LUMIERA_RECCONDITION_WAIT(expr) \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Reccondition mutex not locked"); \ + lumiera_reccondition_wait (lumiera_lock_section_.lock, \ + NOBUG_FLAG_RAW(lumiera_lock_section_.flag), \ + &lumiera_lock_section_.rh); \ } while (!(expr)) +/** + * Timed wait for a condition. + * Must be used inside a RECCONDITION_SECTION. + * @param expr Recconditon which must become true, else the condition variable goes back into sleep + * @param timeout time when the wait expired + * sets LUMIERA_ERROR_LOCK_TIMEOUT when the timeout passed + */ +#define LUMIERA_RECCONDITION_TIMEDWAIT(expr, timeout) \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Reccondition mutex not locked"); \ + if (!lumiera_reccondition_timedwait (lumiera_lock_section_.lock, \ + timeout, \ + lumiera_lock_section_.flag, \ + &lumiera_lock_section_.rh)) \ + break; \ + } while (!(expr)) + + + + /** * Signal a condition variable * Must be used inside a RECCONDITION_SECTION. * Wakes one thread waiting on the condition variable */ -#define LUMIERA_RECCONDITION_SIGNAL \ - do { \ - REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ - TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Signal %p", &lumiera_reccond_section_); \ - pthread_cond_signal (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond); \ +#define LUMIERA_RECCONDITION_SIGNAL \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Reccondition mutex not locked"); \ + lumiera_reccondition_signal (lumiera_lock_section_.lock, \ + lumiera_lock_section_.flag); \ } while (0) @@ -119,11 +135,11 @@ * Must be used inside a RECCONDITION_SECTION. * Wakes all threads waiting on the condition variable */ -#define LUMIERA_RECCONDITION_BROADCAST \ - do { \ - REQUIRE (lumiera_reccond_section_.lock, "Condition recmutex not locked"); \ - TRACE(NOBUG_FLAG_RAW(lumiera_reccond_section_.flag), "Broadcast %p", &lumiera_reccond_section_); \ - pthread_cond_broadcast (&((LumieraReccondition)lumiera_reccond_section_.lock)->cond); \ +#define LUMIERA_RECCONDITION_BROADCAST \ + do { \ + REQUIRE (lumiera_lock_section_.lock, "Reccondition mutex not locked"); \ + lumiera_reccondition_broadcast (lumiera_lock_section_.lock, \ + lumiera_lock_section_.flag); \ } while (0) @@ -159,8 +175,149 @@ LumieraReccondition lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag); -int -lumiera_reccondition_unlock_cb (void* cond); + +static inline LumieraReccondition +lumiera_reccondition_lock (LumieraReccondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire reccondvar", *handle); + + if (pthread_mutex_lock (&self->reccndmutex)) + LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */ + + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + + return self; +} + + +static inline LumieraReccondition +lumiera_reccondition_trylock (LumieraReccondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire reccondvar", *handle); + + int err = pthread_mutex_trylock (&self->reccndmutex); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraReccondition +lumiera_reccondition_timedlock (LumieraReccondition self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire reccondvar", *handle); + + int err = pthread_mutex_timedlock (&self->reccndmutex, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraReccondition +lumiera_reccondition_wait (LumieraReccondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_WAITING, *handle); + + pthread_cond_wait (&self->cond, &self->reccndmutex); + + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_RECURSIVE, *handle); + } + return self; +} + + +static inline LumieraReccondition +lumiera_reccondition_timedwait (LumieraReccondition self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_WAITING, *handle); + + int err; + do { + err = pthread_cond_timedwait (&self->cond, &self->reccndmutex, timeout); + } while(err == EINTR); + + NOBUG_RESOURCE_STATE_RAW (flag, NOBUG_RESOURCE_RECURSIVE, *handle); + + if (err) + { + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + + +static inline void +lumiera_reccondition_signal (LumieraReccondition self, struct nobug_flag* flag) +{ + TRACE(NOBUG_FLAG_RAW(flag), "Signal %p", self); + pthread_cond_signal (&self->cond); +} + + +static inline void +lumiera_reccondition_broadcast (LumieraReccondition self, struct nobug_flag* flag) +{ + TRACE(NOBUG_FLAG_RAW(flag), "Broadcast %p", self); + pthread_cond_broadcast (&self->cond); +} + + +static inline void +lumiera_reccondition_unlock (LumieraReccondition self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + REQUIRE(self); + + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) + { + if (pthread_mutex_unlock (&self->reccndmutex)) + LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */ + } +} + #endif /* diff --git a/src/lib/recmutex.c b/src/lib/recmutex.c index 447a12350..f2a609ac2 100644 --- a/src/lib/recmutex.c +++ b/src/lib/recmutex.c @@ -42,16 +42,17 @@ lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_f { if (self) { - if (recmutexattr_once == PTHREAD_ONCE_INIT) - pthread_once (&recmutexattr_once, recmutexattr_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) { @@ -64,7 +65,6 @@ lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag) return self; } - /* // Local Variables: // mode: C diff --git a/src/lib/recmutex.h b/src/lib/recmutex.h index 204b2fce0..9754e56b1 100644 --- a/src/lib/recmutex.h +++ b/src/lib/recmutex.h @@ -24,6 +24,8 @@ #include "lib/error.h" #include "lib/sectionlock.h" +#include "lib/lockerror.h" +#include "lib/mutex.h" #include #include @@ -36,46 +38,40 @@ /** * Recursive Mutual exclusive section. */ -#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_lock_section_ = { \ - mtx, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", \ - NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->recmutex)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_RECURSIVE, lumiera_lock_section_.rh); \ - } \ - lumiera_lock_section_.lock; \ - }); \ - ({ \ - LUMIERA_MUTEX_SECTION_UNLOCK; \ - })) +#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + lumiera_lock_section_.lock = \ + lumiera_recmutex_lock (mtx, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RECMUTEX_SECTION_UNLOCK; \ + })) -#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_ = { \ - mtx, lumiera_mutex_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_ENTER (nobugflag, (mtx)->rh, "acquire recmutex", \ - NOBUG_RESOURCE_WAITING, lumiera_lock_section_.rh); \ - if (pthread_mutex_lock (&(mtx)->recmutex)) \ - 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_CHAIN(nobugflag, mtx) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + mtx, (lumiera_sectionlock_unlock_fn) lumiera_mutex_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_recmutex_lock (mtx, &NOBUG_FLAG(nobugflag), lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + } \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RECMUTEX_SECTION_UNLOCK; \ + })) #define LUMIERA_RECMUTEX_SECTION_UNLOCK \ @@ -84,7 +80,7 @@ /** - * Mutex. + * Recursive Mutex. * */ struct lumiera_recmutex_struct @@ -112,12 +108,88 @@ lumiera_recmutex_init (LumieraRecmutex self, const char* purpose, struct nobug_f LumieraRecmutex lumiera_recmutex_destroy (LumieraRecmutex self, struct nobug_flag* flag); -/** - * Callback for unlocking mutexes. - * @internal - */ -int -lumiera_mutex_unlock_cb (void* mutex); + +static inline LumieraRecmutex +lumiera_recmutex_lock (LumieraRecmutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire mutex", *handle); + + if (pthread_mutex_lock (&self->recmutex)) + LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */ + + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + + return self; +} + + +static inline LumieraRecmutex +lumiera_recmutex_trylock (LumieraRecmutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire mutex", *handle); + + int err = pthread_mutex_trylock (&self->recmutex); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraRecmutex +lumiera_recmutex_timedlock (LumieraRecmutex self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire mutex", *handle); + + int err = pthread_mutex_timedlock (&self->recmutex, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_RECURSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline void +lumiera_recmutex_unlock (LumieraRecmutex self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + REQUIRE (self); + + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) + { + if (pthread_mutex_unlock (&self->recmutex)) + LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */ + } +} #endif diff --git a/src/lib/rwlock.c b/src/lib/rwlock.c index 60929a458..a62774696 100644 --- a/src/lib/rwlock.c +++ b/src/lib/rwlock.c @@ -23,13 +23,6 @@ #include "lib/rwlock.h" -LUMIERA_ERROR_DEFINE(RWLOCK_AGAIN, "maximum number of readlocks exceed"); -LUMIERA_ERROR_DEFINE(RWLOCK_DEADLOCK, "deadlock detected"); -LUMIERA_ERROR_DEFINE(RWLOCK_DESTROY, "destroying rwlock"); -LUMIERA_ERROR_DEFINE(RWLOCK_UNLOCK, "unlock rwlock failed"); -LUMIERA_ERROR_DEFINE(RWLOCK_RDLOCK, "locking rwlock for reading failed"); -LUMIERA_ERROR_DEFINE(RWLOCK_WRLOCK, "locking rwlock for writing failed"); - /** * @file * Read/write locks. @@ -55,17 +48,12 @@ lumiera_rwlock_destroy (LumieraRWLock self, struct nobug_flag* flag) { NOBUG_RESOURCE_FORGET_RAW (flag, self->rh); if (pthread_rwlock_destroy (&self->rwlock)) - LUMIERA_DIE (RWLOCK_DESTROY); + LUMIERA_DIE (LOCK_DESTROY); } return self; } -int lumiera_rwlock_unlock_cb (void* rwlock) -{ - return pthread_rwlock_unlock (&((LumieraRWLock)rwlock)->rwlock); -} - /* // Local Variables: // mode: C diff --git a/src/lib/rwlock.h b/src/lib/rwlock.h index 57176313d..a059f3767 100644 --- a/src/lib/rwlock.h +++ b/src/lib/rwlock.h @@ -26,15 +26,13 @@ #error "This header must be included with _GNU_SOURCE or _POSIX_C_SOURCE >= 200112L defined" #endif +#include "lib/sectionlock.h" +#include "lib/lockerror.h" + #include +#include #include -LUMIERA_ERROR_DECLARE(RWLOCK_AGAIN); -LUMIERA_ERROR_DECLARE(RWLOCK_DEADLOCK); -LUMIERA_ERROR_DECLARE(RWLOCK_DESTROY); -LUMIERA_ERROR_DECLARE(RWLOCK_UNLOCK); -LUMIERA_ERROR_DECLARE(RWLOCK_RDLOCK); -LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); /** * @file @@ -44,44 +42,41 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); /** * Read locked section. + * readlocks may fail when there are too much readers, one has to check the error afterwards! */ -#define LUMIERA_RDLOCK_SECTION(nobugflag, rwlck) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_lock_section_ = { \ - rwlck, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - RESOURCE_WAIT (nobugflag, (rwlck)->rh, "acquire readlock", lumiera_lock_section_.rh); \ - if (pthread_rwlock_rdlock (&(rwlck)->rwlock)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); \ - } \ - lumiera_lock_section_.lock; \ - }); \ - ({ \ - LUMIERA_RWLOCK_SECTION_UNLOCK; \ +#define LUMIERA_RDLOCK_SECTION(nobugflag, rwlck) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + rwlck, (lumiera_sectionlock_unlock_fn) lumiera_rwlock_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + lumiera_lock_section_.lock = \ + lumiera_rwlock_rdlock (rwlck, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) -#define LUMIERA_RDLOCK_SECTION_CHAIN(nobugflag, rwlck) \ - for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ - rwlck, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_WAIT (nobugflag, (rwlck)->rh, "acquire readlock", lumiera_lock_section_.rh); \ - if (pthread_rwlock_rdlock (&(rwlck)->rwlock)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_SHARED, lumiera_lock_section_.rh); \ - LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ - } \ - lumiera_lock_section_.lock; \ - }); \ - ({ \ - LUMIERA_MUTEX_SECTION_UNLOCK; \ +#define LUMIERA_RDLOCK_SECTION_CHAIN(nobugflag, rwlck) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + rwlck, (lumiera_sectionlock_unlock_fn) lumiera_rwlock_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_rwlock_rdlock (rwlck, &NOBUG_FLAG(nobugflag), lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + } \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) @@ -89,43 +84,39 @@ LUMIERA_ERROR_DECLARE(RWLOCK_WRLOCK); /** * Write locked section. */ -#define LUMIERA_WRLOCK_SECTION(nobugflag, rwlck) \ - for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ - lumiera_lock_section_ = { \ - rwlck, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - RESOURCE_WAIT (nobugflag, (rwlck)->rh, "acquire writelock", lumiera_lock_section_.rh); \ - if (pthread_rwlock_wrlock (&(rwlck)->rwlock)) \ - LUMIERA_DIE (LOCK_ACQUIRE); \ - RESOURCE_STATE (nobugflag, NOBUG_RESOURCE_EXCLUSIVE, lumiera_lock_section_.rh); \ - } \ - lumiera_lock_section_.lock; \ - }); \ - ({ \ - LUMIERA_RWLOCK_SECTION_UNLOCK; \ +#define LUMIERA_WRLOCK_SECTION(nobugflag, rwlck) \ + for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \ + lumiera_lock_section_ = { \ + rwlck, (lumiera_sectionlock_unlock_fn) lumiera_rwlock_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + lumiera_lock_section_.lock = \ + lumiera_rwlock_wrlock (rwlck, &NOBUG_FLAG(nobugflag), &lumiera_lock_section_.rh); \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) -#define LUMIERA_WRLOCK_SECTION_CHAIN(nobugflag, rwlck) \ - for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ - NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ - rwlck, lumiera_rwlock_unlock_cb NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ - ({ \ - if (lumiera_lock_section_.lock) \ - { \ - REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ - RESOURCE_WAIT (nobugflag, (rwlck)->rh, "acquire writelock", lumiera_lock_section_.rh); \ - if (pthread_rwlock_wrlock (&(twlck)->rwlock)) \ - 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_WRLOCK_SECTION_CHAIN(nobugflag, rwlck) \ + for (lumiera_sectionlock *lumiera_lock_section_old_ = &lumiera_lock_section_, \ + NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) lumiera_lock_section_ = { \ + rwlck, (lumiera_sectionlock_unlock_fn) lumiera_rwlock_unlock \ + NOBUG_ALPHA_COMMA(&NOBUG_FLAG(nobugflag)) NOBUG_ALPHA_COMMA_NULL}; \ + ({ \ + if (lumiera_lock_section_.lock) \ + { \ + REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \ + lumiera_lock_section_.lock = \ + lumiera_rwlock_wrlock (rwlck, &NOBUG_FLAG(nobugflag), lumiera_lock_section_.rh); \ + LUMIERA_SECTION_UNLOCK_(lumiera_lock_section_old_); \ + } \ + lumiera_lock_section_.lock; \ + }); \ + ({ \ + LUMIERA_RWLOCK_SECTION_UNLOCK; \ })) @@ -161,9 +152,167 @@ lumiera_rwlock_init (LumieraRWLock self, const char* purpose, struct nobug_flag* LumieraRWLock lumiera_rwlock_destroy (LumieraRWLock self, struct nobug_flag* flag); +static inline LumieraRWLock +lumiera_rwlock_rdlock (LumieraRWLock self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire rwlock for reading", *handle); + + int err = pthread_rwlock_rdlock (&self->rwlock); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_SHARED, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraRWLock +lumiera_rwlock_tryrdlock (LumieraRWLock self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire rwlock for reading", *handle); + + int err = pthread_rwlock_tryrdlock (&self->rwlock); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_SHARED, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraRWLock +lumiera_rwlock_timedrdlock (LumieraRWLock self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire rwlock for reading", *handle); + + int err = pthread_rwlock_timedrdlock (&self->rwlock, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_SHARED, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraRWLock +lumiera_rwlock_wrlock (LumieraRWLock self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + RESOURCE_WAIT (NOBUG_FLAG_RAW(flag), self->rh, "acquire rwlock for writing", *handle); + + if (pthread_rwlock_wrlock (&self->rwlock)) + LUMIERA_DIE (LOCK_ACQUIRE); /* never reached (in a correct program) */ + + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + + return self; +} + + +static inline LumieraRWLock +lumiera_rwlock_trywrlock (LumieraRWLock self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "try acquire rwlock for writing", *handle); + + int err = pthread_rwlock_trywrlock (&self->rwlock); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline LumieraRWLock +lumiera_rwlock_timedwrlock (LumieraRWLock self, + const struct timespec* timeout, + struct nobug_flag* flag, + struct nobug_resource_user** handle) +{ + if (self) + { + NOBUG_RESOURCE_TRY (NOBUG_FLAG_RAW(flag), self->rh, "timed acquire rwlock for writing", *handle); + + int err = pthread_rwlock_timedwrlock (&self->rwlock, timeout); + + if (!err) + { + RESOURCE_STATE (NOBUG_FLAG_RAW(flag), NOBUG_RESOURCE_EXCLUSIVE, *handle); + } + else + { + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) /*{}*/; + lumiera_lockerror_set (err, flag, __func__); + return NULL; + } + } + + return self; +} + + +static inline void +lumiera_rwlock_unlock (LumieraRWLock self, struct nobug_flag* flag, struct nobug_resource_user** handle) +{ + REQUIRE(self); + + NOBUG_RESOURCE_LEAVE_RAW(flag, *handle) + { + if (pthread_rwlock_unlock (&self->rwlock)) + LUMIERA_DIE (LOCK_RELEASE); /* never reached (in a correct program) */ + } +} + -int -lumiera_rwlock_unlock_cb (void* rwlock); #endif diff --git a/src/lib/sectionlock.h b/src/lib/sectionlock.h index 42e719de7..a0a751ce7 100644 --- a/src/lib/sectionlock.h +++ b/src/lib/sectionlock.h @@ -22,17 +22,11 @@ #ifndef LUMIERA_SECTIONLOCK_H #define LUMIERA_SECTIONLOCK_H -#include "lib/error.h" - #include #include -LUMIERA_ERROR_DECLARE (LOCK_ACQUIRE); -LUMIERA_ERROR_DECLARE (LOCK_RELEASE); -LUMIERA_ERROR_DECLARE (LOCK_DESTROY); - -typedef int (*lumiera_sectionlock_unlock_fn)(void*); +typedef int (*lumiera_sectionlock_unlock_fn)(void*, struct nobug_flag* flag, struct nobug_resource_user** handle); /** * sectionlock used to manage the state of mutexes. @@ -55,22 +49,17 @@ lumiera_sectionlock_ensureunlocked (LumieraSectionlock self) } - /** * 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) \ - { \ - NOBUG_RESOURCE_LEAVE_RAW((section)->flag, (section)->rh) \ - { \ - if ((section)->unlock((section)->lock)) \ - LUMIERA_DIE (LOCK_RELEASE); \ - (section)->lock = NULL; \ - } \ +#define LUMIERA_SECTION_UNLOCK_(section) \ + do if ((section)->lock) \ + { \ + (section)->unlock((section)->lock, (section)->flag, &(section)->rh); \ + (section)->lock = NULL; \ } while (0) diff --git a/src/proc/Makefile.am b/src/proc/Makefile.am index 51371e560..7d4d331df 100644 --- a/src/proc/Makefile.am +++ b/src/proc/Makefile.am @@ -172,6 +172,7 @@ liblumiprocmobjectsession_la_SOURCES = \ $(liblumiprocmobjectsession_la_srcdir)/mobjectfactory.cpp \ $(liblumiprocmobjectsession_la_srcdir)/placement-index.cpp \ $(liblumiprocmobjectsession_la_srcdir)/query-resolver.cpp \ + $(liblumiprocmobjectsession_la_srcdir)/query-focus.cpp \ $(liblumiprocmobjectsession_la_srcdir)/placement-index-query-resolver.cpp \ $(liblumiprocmobjectsession_la_srcdir)/session-services.cpp \ $(liblumiprocmobjectsession_la_srcdir)/root.cpp \ diff --git a/tests/components/Makefile.am b/tests/components/Makefile.am index c29ee5274..04eb5a685 100644 --- a/tests/components/Makefile.am +++ b/tests/components/Makefile.am @@ -33,59 +33,67 @@ test_components_LDADD = \ liblumiera.la \ $(NOBUGMT_LUMIERA_LIBS) -ldl -lboost_program_options-mt -lboost_regex-mt -test_components_SOURCES = \ - $(testcomponents_srcdir)/backend/mediaaccessmock.cpp \ - $(testcomponents_srcdir)/backend/mediaaccessmocktest.cpp \ - $(testcomponents_srcdir)/proc/asset/assetcategorytest.cpp \ - $(testcomponents_srcdir)/proc/asset/compoundmediatest.cpp \ - $(testcomponents_srcdir)/proc/asset/deleteassettest.cpp \ - $(testcomponents_srcdir)/proc/asset/identityofassetstest.cpp \ - $(testcomponents_srcdir)/proc/asset/mediastructurequerytest.cpp \ - $(testcomponents_srcdir)/proc/asset/basicpipetest.cpp \ - $(testcomponents_srcdir)/proc/asset/createassettest.cpp \ - $(testcomponents_srcdir)/proc/asset/dependent-assets-test.cpp \ - $(testcomponents_srcdir)/proc/asset/makecliptest.cpp \ - $(testcomponents_srcdir)/proc/asset/orderingofassetstest.cpp \ - $(testcomponents_srcdir)/proc/asset/testasset.cpp \ - $(testcomponents_srcdir)/proc/control/command-basic-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-argument-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-equality-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-mutation-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-clone-builder-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-use1-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-use2-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-use3-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-binding-test.cpp \ - $(testcomponents_srcdir)/proc/control/command-registry-test.cpp \ - $(testcomponents_srcdir)/proc/control/test-dummy-commands.cpp \ - $(testcomponents_srcdir)/proc/control/argument-tuple-accept-test.cpp \ - $(testcomponents_srcdir)/proc/control/memento-tie-test.cpp \ +test_components_SOURCES = \ + $(testcomponents_srcdir)/backend/mediaaccessmock.cpp \ + $(testcomponents_srcdir)/backend/mediaaccessmocktest.cpp \ + $(testcomponents_srcdir)/proc/asset/assetcategorytest.cpp \ + $(testcomponents_srcdir)/proc/asset/compoundmediatest.cpp \ + $(testcomponents_srcdir)/proc/asset/deleteassettest.cpp \ + $(testcomponents_srcdir)/proc/asset/identityofassetstest.cpp \ + $(testcomponents_srcdir)/proc/asset/mediastructurequerytest.cpp \ + $(testcomponents_srcdir)/proc/asset/basicpipetest.cpp \ + $(testcomponents_srcdir)/proc/asset/createassettest.cpp \ + $(testcomponents_srcdir)/proc/asset/dependent-assets-test.cpp \ + $(testcomponents_srcdir)/proc/asset/makecliptest.cpp \ + $(testcomponents_srcdir)/proc/asset/orderingofassetstest.cpp \ + $(testcomponents_srcdir)/proc/asset/testasset.cpp \ + $(testcomponents_srcdir)/proc/control/command-basic-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-argument-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-equality-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-mutation-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-clone-builder-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-use1-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-use2-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-use3-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-binding-test.cpp \ + $(testcomponents_srcdir)/proc/control/command-registry-test.cpp \ + $(testcomponents_srcdir)/proc/control/test-dummy-commands.cpp \ + $(testcomponents_srcdir)/proc/control/argument-tuple-accept-test.cpp \ + $(testcomponents_srcdir)/proc/control/memento-tie-test.cpp \ $(testcomponents_srcdir)/proc/control/handling-pattern-basics-test.cpp \ $(testcomponents_srcdir)/proc/control/handling-pattern-standard-impl-test.cpp \ - $(testcomponents_srcdir)/proc/engine/buff-table-test.cpp \ - $(testcomponents_srcdir)/proc/engine/node-basic-test.cpp \ - $(testcomponents_srcdir)/proc/engine/node-fabrication-test.cpp \ - $(testcomponents_srcdir)/proc/engine/node-operation-test.cpp \ - $(testcomponents_srcdir)/proc/engine/node-source-test.cpp \ - $(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \ - $(testcomponents_srcdir)/proc/mobject/builder/buildsegmenttest.cpp \ - $(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \ - $(testcomponents_srcdir)/proc/mobject/mobject-ref-test.cpp \ - $(testcomponents_srcdir)/proc/mobject/placement-basic-test.cpp \ - $(testcomponents_srcdir)/proc/mobject/placement-hierarchy-test.cpp \ - $(testcomponents_srcdir)/proc/mobject/placement-ref-test.cpp \ + $(testcomponents_srcdir)/proc/engine/buff-table-test.cpp \ + $(testcomponents_srcdir)/proc/engine/node-basic-test.cpp \ + $(testcomponents_srcdir)/proc/engine/node-fabrication-test.cpp \ + $(testcomponents_srcdir)/proc/engine/node-operation-test.cpp \ + $(testcomponents_srcdir)/proc/engine/node-source-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \ + $(testcomponents_srcdir)/proc/mobject/builder/buildsegmenttest.cpp \ + $(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \ + $(testcomponents_srcdir)/proc/mobject/mobject-ref-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/placement-basic-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/placement-hierarchy-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/placement-ref-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/test-scopes.cpp \ $(testcomponents_srcdir)/proc/mobject/session/placement-index-test.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/addcliptest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/deletecliptest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/rebuildfixturetest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/sessionmanagertest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/testclip.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/defsmanagerimpltest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/defsmanagertest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/defsregistryimpltest.cpp \ - $(testcomponents_srcdir)/proc/mobject/session/sessionstructuretest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/addcliptest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/deletecliptest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/rebuildfixturetest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/sessionmanagertest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/testclip.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/defsmanagerimpltest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/defsmanagertest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/defsregistryimpltest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/sessionstructuretest.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/scope-query-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/placement-index-query-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/query-focus-stack-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/query-resolver-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/query-focus-test.cpp \ + $(testcomponents_srcdir)/proc/mobject/session/session-service-access-test.cpp \ $(testcomponents_srcdir)/mainsuite.cpp + noinst_HEADERS += \ $(testcomponents_srcdir)/backend/mediaaccessmock.hpp \ $(testcomponents_srcdir)/proc/asset/testclipasset.hpp \ diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 7362c6caf..d3626c720 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -46,11 +46,16 @@ test_lib_SOURCES = \ $(testlib_srcdir)/factorytest.cpp \ $(testlib_srcdir)/format-helper-test.cpp \ $(testlib_srcdir)/functor-util-test.cpp \ + $(testlib_srcdir)/util-foreach-test.cpp \ $(testlib_srcdir)/hash-indexed-test.cpp \ $(testlib_srcdir)/helloworldtest.cpp \ $(testlib_srcdir)/lifecycletest.cpp \ $(testlib_srcdir)/multifact-test.cpp \ + $(testlib_srcdir)/multifact-argument-test.cpp \ $(testlib_srcdir)/iter-adapter-test.cpp \ + $(testlib_srcdir)/item-wrapper-test.cpp \ + $(testlib_srcdir)/itertools-test.cpp \ + $(testlib_srcdir)/iter-source-test.cpp \ $(testlib_srcdir)/meta/typelist-test.cpp \ $(testlib_srcdir)/meta/typelist-manip-test.cpp \ $(testlib_srcdir)/meta/typeseq-manip-test.cpp \ @@ -60,6 +65,8 @@ test_lib_SOURCES = \ $(testlib_srcdir)/meta/function-erasure-test.cpp \ $(testlib_srcdir)/meta/generator-test.cpp \ $(testlib_srcdir)/meta/config-flags-test.cpp \ + $(testlib_srcdir)/meta/duck-detector-test.cpp \ + $(testlib_srcdir)/meta/iterable-classification-test.cpp \ $(testlib_srcdir)/query/queryutilstest.cpp \ $(testlib_srcdir)/removefromsettest.cpp \ $(testlib_srcdir)/sanitised-identifier-test.cpp \