Merge branch 'master' of git://git.lumiera.org/LUMIERA

This commit is contained in:
Michael Ploujnikov 2010-01-13 19:12:15 -05:00
commit a045479c63
19 changed files with 1133 additions and 376 deletions

View file

@ -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 \

View file

@ -2,7 +2,7 @@
condition.c - condition variable
Copyright (C) Lumiera.org
2008, 2009 Christian Thaeter <ct@pipapo.org>
2008, 2009, 2010, 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
@ -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:
*/

View file

@ -2,7 +2,7 @@
condition.h - condition variables
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
2008, 2010, 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
@ -24,8 +24,11 @@
#include "lib/error.h"
#include "lib/sectionlock.h"
#include "lib/lockerror.h"
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <nobug.h>
/**
@ -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

View file

@ -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 */

View file

@ -164,6 +164,7 @@ lumiera_error_peek (void);
predefined errors
*/
LUMIERA_ERROR_DECLARE (ERRNO);
LUMIERA_ERROR_DECLARE (UNKNOWN);
#ifdef __cplusplus
} /* extern "C" */

79
src/lib/lockerror.c Normal file
View file

@ -0,0 +1,79 @@
/*
lockerror.c - error declarations for all locks (mutex, rwlocks, cond vars)
Copyright (C) Lumiera.org
2010, 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/lockerror.h"
#include <errno.h>
/* 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:
*/

53
src/lib/lockerror.h Normal file
View file

@ -0,0 +1,53 @@
/*
lockerror.h - error declarations for all locks (mutex, rwlocks, cond vars)
Copyright (C) Lumiera.org
2010, 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_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:
*/

View file

@ -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:

View file

@ -24,8 +24,10 @@
#include "lib/error.h"
#include "lib/sectionlock.h"
#include "lib/lockerror.h"
#include <pthread.h>
#include <time.h>
#include <nobug.h>
/**
@ -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

View file

@ -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:
*/

View file

@ -2,7 +2,7 @@
reccondition.h - recursive locked condition variables
Copyright (C) Lumiera.org
2008, 2009, Christian Thaeter <ct@pipapo.org>
2008, 2009, 2010, 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
@ -24,8 +24,11 @@
#include "lib/error.h"
#include "lib/sectionlock.h"
#include "lib/lockerror.h"
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <nobug.h>
/**
@ -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
/*

View file

@ -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

View file

@ -24,6 +24,8 @@
#include "lib/error.h"
#include "lib/sectionlock.h"
#include "lib/lockerror.h"
#include "lib/mutex.h"
#include <pthread.h>
#include <nobug.h>
@ -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

View file

@ -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

View file

@ -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 <pthread.h>
#include <time.h>
#include <nobug.h>
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

View file

@ -22,17 +22,11 @@
#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*);
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)

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \