New condition and reccondition implementation

Should be working but not thoroughly tested still, docs not complete
This commit is contained in:
Christian Thaeter 2009-01-27 10:10:03 +01:00
parent 4f29f302b2
commit d91620a60f
6 changed files with 259 additions and 174 deletions

View file

@ -2,7 +2,7 @@
condition.c - condition variable
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
2008, 2009 Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -26,8 +26,6 @@
* Condition variables
*/
LUMIERA_ERROR_DEFINE (CONDITION_DESTROY, "condition destroy failed");
LumieraCondition
lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug_flag* flag)
@ -35,7 +33,7 @@ lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug
if (self)
{
pthread_cond_init (&self->cond, NULL);
pthread_mutex_init (&self->mutex, NULL);
pthread_mutex_init (&self->cndmutex, NULL);
NOBUG_RESOURCE_HANDLE_INIT (self->rh);
NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "cond_var", purpose, self, self->rh);
}
@ -50,15 +48,21 @@ lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag)
{
NOBUG_RESOURCE_FORGET_RAW (flag, self->rh);
if (pthread_mutex_destroy (&self->mutex))
LUMIERA_DIE (MUTEX_DESTROY);
if (pthread_mutex_destroy (&self->cndmutex))
LUMIERA_DIE (LOCK_DESTROY);
if (pthread_cond_destroy (&self->cond))
LUMIERA_DIE (CONDITION_DESTROY);
LUMIERA_DIE (LOCK_DESTROY);
}
return self;
}
int lumiera_condition_unlock_cb (void* cond)
{
return pthread_mutex_unlock (&((LumieraCondition)cond)->cndmutex);
}

View file

@ -23,58 +23,73 @@
#define LUMIERA_CONDITION_H
#include "lib/error.h"
#include "lib/mutex.h"
#include "lib/sectionlock.h"
#include <pthread.h>
#include <nobug.h>
/**
* @file
* Condition variables, header
*/
LUMIERA_ERROR_DECLARE (CONDITION_DESTROY);
/**
* Condition section.
* Locks the condition mutex, one can use LUMIERA_CONDITION_WAIT to wait for signals or
* LUMIERA_CONDITION_SIGNAL or LUMIERA_CONDITION_BROADCAST to wake waiting threads
* Condition variables must be at the end of locking chains, they can not be used at
* intermediate position.
* @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_conditionacquirer NOBUG_CLEANUP(lumiera_conditionacquirer_ensureunlocked) \
lumiera_condition_section_ = {(LumieraCondition)1}; \
lumiera_condition_section_.condition;) \
for ( \
({ \
lumiera_condition_section_.condition = (cnd); \
NOBUG_IF(NOBUG_MODE_ALPHA, lumiera_condition_section_.flag = &NOBUG_FLAG(nobugflag)); \
NOBUG_RESOURCE_HANDLE_INIT (lumiera_condition_section_.rh); \
RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condition", &lumiera_condition_section_, \
NOBUG_RESOURCE_EXCLUSIVE, lumiera_condition_section_.rh); \
if (pthread_mutex_lock (&(cnd)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
}); \
lumiera_condition_section_.condition; \
({ \
LUMIERA_CONDITION_UNLOCK \
#define LUMIERA_CONDITION_SECTION(nobugflag, cnd) \
for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
lumiera_cond_section_ = { \
(void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
lumiera_cond_section_.lock;) \
for ( \
({ \
lumiera_cond_section_.lock = (cnd); \
NOBUG_IF_ALPHA(lumiera_cond_section_.flag = &NOBUG_FLAG(nobugflag);) \
RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condmutex", &lumiera_cond_section_, \
NOBUG_RESOURCE_WAITING, 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; \
}))
/**
* Explicit mutex unlock for a condition variable
* One can early unlock the mutex of a condition variable prior leaving a CONDITION_SECTION.
* The CONDITION_WAIT, CONDITION_SIGNAL and CONDITION_BROADCAST macros must not be used after the mutex
* got unlocked.
* @param nobugflag NoBug flag used to log actions on the condition
*/
#define LUMIERA_CONDITION_UNLOCK \
if (lumiera_condition_section_.condition) \
{ \
pthread_mutex_unlock (&lumiera_condition_section_.condition->mutex); \
lumiera_condition_section_.condition = NULL; \
NOBUG_RESOURCE_LEAVE_RAW(lumiera_condition_section_.flag, lumiera_condition_section_.rh); \
}
#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_ = { \
(void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
lumiera_cond_section_.lock;) \
for ( \
({ \
REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \
lumiera_cond_section_.lock = cnd; \
NOBUG_IF_ALPHA(lumiera_cond_section_.flag = &NOBUG_FLAG(nobugflag);) \
RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire condmutex", &lumiera_cond_section_, \
NOBUG_RESOURCE_WAITING, 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_UNLOCK \
LUMIERA_SECTION_UNLOCK_(&lumiera_cond_section_)
/**
@ -82,12 +97,13 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY);
* 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 { \
ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \
NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_WAITING); \
pthread_cond_wait (&lumiera_condition_section_.condition->cond, &lumiera_condition_section_.condition->mutex); \
NOBUG_RESOURCE_STATE_RAW (lumiera_condition_section_.flag, lumiera_condition_section_.rh, NOBUG_RESOURCE_EXCLUSIVE);\
#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); \
} while (!(expr))
@ -96,12 +112,12 @@ LUMIERA_ERROR_DECLARE (CONDITION_DESTROY);
* Must be used inside a CONDITION_SECTION.
* Wakes one thread waiting on the condition variable
*/
#define LUMIERA_CONDITION_SIGNAL \
do { \
ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \
NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Signaling")); \
pthread_cond_signal (&lumiera_condition_section_.condition->cond); \
} while (0)
#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); \
} while (0)
/**
@ -109,13 +125,12 @@ do {
* Must be used inside a CONDITION_SECTION.
* Wakes all threads waiting on the condition variable
*/
#define LUMIERA_CONDITION_BROADCAST \
do { \
ENSURE (lumiera_condition_section_.condition, "Condition mutex not locked"); \
NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_condition_section_.flag, "Broadcasting")); \
pthread_cond_broadcast (&lumiera_condition_section_.condition->cond); \
} while (0)
#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); \
} while (0)
/**
@ -125,7 +140,7 @@ do {
struct lumiera_condition_struct
{
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_mutex_t cndmutex;
RESOURCE_HANDLE (rh);
};
typedef struct lumiera_condition_struct lumiera_condition;
@ -149,26 +164,8 @@ lumiera_condition_init (LumieraCondition self, const char* purpose, struct nobug
LumieraCondition
lumiera_condition_destroy (LumieraCondition self, struct nobug_flag* flag);
/**
* conditionacquirer used to manage the state of a condition variable.
*/
struct lumiera_conditionacquirer_struct
{
LumieraCondition condition;
NOBUG_IF(NOBUG_MODE_ALPHA, struct nobug_flag* flag);
RESOURCE_HANDLE (rh);
};
typedef struct lumiera_conditionacquirer_struct lumiera_conditionacquirer;
typedef struct lumiera_conditionacquirer_struct* LumieraConditionacquirer;
/* helper function for nobug */
static inline void
lumiera_conditionacquirer_ensureunlocked (LumieraConditionacquirer self)
{
ENSURE (!self->condition, "forgot to unlock condition variable");
}
int
lumiera_condition_unlock_cb (void* cond);
#endif

View file

@ -2,7 +2,7 @@
reccondition.c - condition variable, w/ recursive mutex
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
2008, 2009, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -19,7 +19,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "lib/condition.h"
#include "lib/reccondition.h"
/**
@ -48,7 +47,7 @@ lumiera_reccondition_init (LumieraReccondition self, const char* purpose, struct
pthread_once (&recursive_mutexattr_once, recursive_mutexattr_init);
pthread_cond_init (&self->cond, NULL);
pthread_mutex_init (&self->mutex, &recursive_mutexattr);
pthread_mutex_init (&self->reccndmutex, &recursive_mutexattr);
NOBUG_RESOURCE_HANDLE_INIT (self->rh);
NOBUG_RESOURCE_ANNOUNCE_RAW (flag, "reccond_var", purpose, self, self->rh);
}
@ -63,15 +62,19 @@ lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag)
{
NOBUG_RESOURCE_FORGET_RAW (flag, self->rh);
if (pthread_mutex_destroy (&self->mutex))
if (pthread_mutex_destroy (&self->reccndmutex))
LUMIERA_DIE (LOCK_DESTROY);
if (pthread_cond_destroy (&self->cond))
LUMIERA_DIE (CONDITION_DESTROY);
LUMIERA_DIE (LOCK_DESTROY);
}
return self;
}
int lumiera_reccondition_unlock_cb (void* cond)
{
return pthread_mutex_unlock (&((LumieraReccondition)cond)->reccndmutex);
}

View file

@ -1,8 +1,8 @@
/*
reccondition.h - condition variables, w/ recursive mutex
reccondition.h - recursive locked condition variables
Copyright (C) Lumiera.org
2008, Christian Thaeter <ct@pipapo.org>
2008, 2009, Christian Thaeter <ct@pipapo.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -23,106 +23,122 @@
#define LUMIERA_RECCONDITION_H
#include "lib/error.h"
#include "lib/mutex.h"
#include "lib/sectionlock.h"
#include <pthread.h>
#include <nobug.h>
/**
* @file
* Reccondition variables. Same as Conditon variables but using a recursive mutex for locking.
* Condition variables, header
*/
/**
* Reccondition section.
* Locks the reccondition mutex, one can then use LUMIERA_RECCONDITION_WAIT to wait for signals or
* Recursive Condition section.
* Locks the condition mutex, one can use LUMIERA_RECCONDITION_WAIT to wait for signals or
* LUMIERA_RECCONDITION_SIGNAL or LUMIERA_RECCONDITION_BROADCAST to wake waiting threads
* @param nobugflag NoBug flag used to log actions on the reccondition
* @param rcnd Reccondition variable to be locked
* @param nobugflag NoBug flag used to log actions on the condition
* @param cnd Condition variable to be locked
*/
#define LUMIERA_RECCONDITION_SECTION(nobugflag, rcnd) \
for (lumiera_recconditionacquirer NOBUG_CLEANUP(lumiera_recconditionacquirer_ensureunlocked) \
lumiera_reccondition_section_ = {(LumieraReccondition)1}; \
lumiera_reccondition_section_.reccondition;) \
for ( \
({ \
lumiera_reccondition_section_.reccondition = (rcnd); \
NOBUG_IF(NOBUG_MODE_ALPHA, lumiera_reccondition_section_.flag = &NOBUG_FLAG(nobugflag)); \
NOBUG_RESOURCE_HANDLE_INIT (lumiera_reccondition_section_.rh); \
RESOURCE_ENTER (nobugflag, (rcnd)->rh, "acquire reccondition", &lumiera_reccondition_section_, \
NOBUG_RESOURCE_RECURSIVE, lumiera_reccondition_section_.rh); \
if (pthread_mutex_lock (&(rcnd)->mutex)) LUMIERA_DIE (MUTEX_LOCK); \
}); \
lumiera_reccondition_section_.reccondition; \
({ \
LUMIERA_RECCONDITION_UNLOCK(nobugflag) \
#define LUMIERA_RECCONDITION_SECTION(nobugflag, cnd) \
for (lumiera_sectionlock NOBUG_CLEANUP(lumiera_sectionlock_ensureunlocked) \
lumiera_reccond_section_ = { \
(void*)1, lumiera_condition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
lumiera_reccond_section_.lock;) \
for ( \
({ \
lumiera_reccond_section_.lock = (cnd); \
NOBUG_IF_ALPHA(lumiera_reccond_section_.flag = &NOBUG_FLAG(nobugflag);) \
RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire reccondmutex", &lumiera_reccond_section_, \
NOBUG_RESOURCE_WAITING, 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; \
}))
/**
* Explicit mutex unlock for a reccondition variable
* One can early unlock the mutex of a condition variable prior leaving a RECCONDITION_SECTION.
* The RECCONDITION_WAIT, RECCONDITION_SIGNAL and RECCONDITION_BROADCAST macros must not be used after the mutex
* got unlocked.
* @param nobugflag NoBug flag used to log actions on the reccondition
*/
#define LUMIERA_RECCONDITION_UNLOCK \
if (lumiera_reccondition_section_.reccondition) \
{ \
pthread_mutex_unlock (&lumiera_reccondition_section_.reccondition->mutex); \
lumiera_reccondition_section_.reccondition = NULL; \
RESOURCE_LEAVE(nobugflag, lumiera_reccondition_section_.rh); \
}
#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_ = { \
(void*)1, lumiera_reccondition_unlock_cb NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA_NULL}; \
lumiera_reccond_section_.lock;) \
for ( \
({ \
REQUIRE (lumiera_lock_section_old_->lock, "section prematurely unlocked"); \
lumiera_reccond_section_.lock = (cnd); \
NOBUG_IF_ALPHA(lumiera_reccond_section_.flag = &NOBUG_FLAG(nobugflag);) \
RESOURCE_ENTER (nobugflag, (cnd)->rh, "acquire reccondmutex", &lumiera_reccond_section_, \
NOBUG_RESOURCE_WAITING, 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_UNLOCK \
LUMIERA_SECTION_UNLOCK_(&lumiera_reccond_section_)
/**
* Wait for a reccondition.
* Wait for a condition.
* Must be used inside a RECCONDITION_SECTION.
* @param expr Recconditon which must become true, else the reccondition variable goes back into sleep
* @param expr Conditon which must become true, else the condition variable goes back into sleep
*/
#define LUMIERA_RECCONDITION_WAIT(expr) \
do { \
ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \
NOBUG_RESOURCE_STATE_RAW (lumiera_reccondition_section_.flag, lumiera_reccondition_section_.rh, NOBUG_RESOURCE_WAITING); \
pthread_cond_wait (&lumiera_reccondition_section_.reccondition->cond, &lumiera_reccondition_section_.reccondition->mutex); \
NOBUG_RESOURCE_STATE_RAW (lumiera_reccondition_section_.flag, lumiera_reccondition_section_.rh, NOBUG_RESOURCE_RECURSIVE); \
#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 (&((LumieraCondition)lumiera_reccond_section_.lock)->cond, \
&((LumieraCondition)lumiera_reccond_section_.lock)->cndmutex); \
NOBUG_RESOURCE_STATE_RAW (lumiera_reccond_section_.flag, NOBUG_RESOURCE_RECURSIVE, lumiera_reccond_section_.rh); \
} while (!(expr))
/**
* Signal a reccondition variable
* Signal a condition variable
* Must be used inside a RECCONDITION_SECTION.
* Wakes one thread waiting on the condition variable
*/
#define LUMIERA_RECCONDITION_SIGNAL \
do { \
ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \
NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_reccondition_section_.flag, "Signaling")); \
pthread_cond_signal (&lumiera_reccondition_section_.reccondition->cond); \
} while (0)
#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 (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \
} while (0)
/**
* Broadcast a reccondition variable
* Broadcast a condition variable
* Must be used inside a RECCONDITION_SECTION.
* Wakes all threads waiting on the reccondition variable
* Wakes all threads waiting on the condition variable
*/
#define LUMIERA_RECCONDITION_BROADCAST \
do { \
ENSURE (lumiera_reccondition_section_.reccondition, "Reccondition mutex not locked"); \
NOBUG_IF(NOBUG_MODE_ALPHA, TRACE(lumiera_reccondition_section_.flag, "Broadcasting"));\
pthread_cond_broadcast (&lumiera_reccondition_section_.reccondition->cond); \
} while (0)
#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 (&((LumieraCondition)lumiera_reccond_section_.lock)->cond); \
} while (0)
/**
* Reccondition variables.
* Condition variables. Recursive mutex variant.
*
*/
struct lumiera_reccondition_struct
{
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_mutex_t reccndmutex;
RESOURCE_HANDLE (rh);
};
typedef struct lumiera_reccondition_struct lumiera_reccondition;
@ -130,8 +146,8 @@ typedef lumiera_reccondition* LumieraReccondition;
/**
* Initialize a reccondition variable
* @param self is a pointer to the reccondition variable to be initialized
* Initialize a condition variable
* @param self is a pointer to the condition variable to be initialized
* @return self as given
*/
LumieraReccondition
@ -139,34 +155,16 @@ lumiera_reccondition_init (LumieraReccondition self, const char* purpose, struct
/**
* Destroy a reccondition variable
* @param self is a pointer to the reccondition variable to be destroyed
* Destroy a condition variable
* @param self is a pointer to the condition variable to be destroyed
* @return self as given
*/
LumieraReccondition
lumiera_reccondition_destroy (LumieraReccondition self, struct nobug_flag* flag);
/**
* recconditionacquirer used to manage the state of a reccondition variable.
*/
struct lumiera_recconditionacquirer_struct
{
LumieraReccondition reccondition;
NOBUG_IF(NOBUG_MODE_ALPHA, struct nobug_flag* flag);
RESOURCE_HANDLE (rh);
};
typedef struct lumiera_recconditionacquirer_struct lumiera_recconditionacquirer;
typedef struct lumiera_recconditionacquirer_struct* LumieraRecconditionacquirer;
/* helper function for nobug */
static inline void
lumiera_recconditionacquirer_ensureunlocked (LumieraRecconditionacquirer self)
{
ENSURE (!self->reccondition, "forgot to unlock reccondition variable");
}
int
lumiera_reccondition_unlock_cb (void* cond);
#endif
/*

View file

@ -70,3 +70,19 @@ PLANNED "condition broadcasting" <<END
END
TEST "reccondition not unlocked asserts" recconditionforgotunlock <<END
return: 134
END
TEST "reccondition section" recconditionsection <<END
out: reccondition locked section 1
out: reccondition locked section 2
END
PLANNED "reccondition signaling" <<END
END
PLANNED "reccondition broadcasting" <<END
END

View file

@ -219,6 +219,22 @@ TEST ("rwdeadlockrw")
}
TEST ("conditionops (compiletest only)")
{
lumiera_condition cond;
lumiera_condition_init (&cond, "conditionsection", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_CONDITION_SECTION (NOBUG_ON, &cond)
{
LUMIERA_CONDITION_WAIT(1);
LUMIERA_CONDITION_SIGNAL;
LUMIERA_CONDITION_BROADCAST;
}
lumiera_condition_destroy (&cond, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("conditionsection")
{
lumiera_condition cond;
@ -251,4 +267,55 @@ TEST ("conditionforgotunlock")
lumiera_condition_destroy (&cond, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("recconditionops (compiletest only)")
{
lumiera_reccondition reccond;
lumiera_reccondition_init (&reccond, "recconditionsection", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &reccond)
{
LUMIERA_RECCONDITION_WAIT(1);
LUMIERA_RECCONDITION_SIGNAL;
LUMIERA_RECCONDITION_BROADCAST;
}
lumiera_reccondition_destroy (&reccond, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("recconditionsection")
{
lumiera_reccondition reccond;
lumiera_reccondition_init (&reccond, "recconditionsection", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &reccond)
{
printf ("reccondition locked section 1\n");
}
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &reccond)
{
printf ("reccondition locked section 2\n");
}
lumiera_reccondition_destroy (&reccond, &NOBUG_FLAG(NOBUG_ON));
}
TEST ("recconditionforgotunlock")
{
lumiera_reccondition reccond;
lumiera_reccondition_init (&reccond, "recconditionforgotunlock", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_RECCONDITION_SECTION (NOBUG_ON, &reccond)
{
break; // RECCONDITION_SECTIONS must not be left by a jump
}
lumiera_reccondition_destroy (&reccond, &NOBUG_FLAG(NOBUG_ON));
}
TESTS_END