diff --git a/src/lib/locking.h b/src/lib/locking.h index 5c6549f31..fce854b0d 100644 --- a/src/lib/locking.h +++ b/src/lib/locking.h @@ -23,6 +23,7 @@ #define CINELERRA_LOCKING_H #include +#include #include #include "lib/error.h" diff --git a/src/lib/mutex.h b/src/lib/mutex.h index 3110e399d..d9a26ef61 100644 --- a/src/lib/mutex.h +++ b/src/lib/mutex.h @@ -78,6 +78,22 @@ cinelerra_mutexacquirer_ensureunlocked (CinelerraMutexacquirer self) cinelerra_mutexacquirer NOBUG_CLEANUP(cinelerra_mutexacquirer_ensureunlocked) +/** + * initialize a mutexacquirer state without mutex. + * @param self mutexacquirer to be initialized, must be an automatic variable + * @return self as given + * This initialization is used when cinelerra_mutexacquirer_try_mutex shall be used later + */ +static inline CinelerraMutexacquirer +cinelerra_mutexacquirer_init (CinelerraMutexacquirer self) +{ + REQUIRE (self); + self->mutex = NULL; + self->state = CINELERRA_UNLOCKED; + + return self; +} + /** * initialize a mutexacquirer state * @param self mutexacquirer to be initialized, must be an automatic variable @@ -87,7 +103,7 @@ cinelerra_mutexacquirer NOBUG_CLEANUP(cinelerra_mutexacquirer_ensureunlocked) * errors are fatal */ static inline CinelerraMutexacquirer -cinelerra_mutexacquirer_init (CinelerraMutexacquirer self, CinelerraMutex mutex, enum cinelerra_lockstate state) +cinelerra_mutexacquirer_init_mutex (CinelerraMutexacquirer self, CinelerraMutex mutex, enum cinelerra_lockstate state) { REQUIRE (self); REQUIRE (mutex); @@ -100,6 +116,7 @@ cinelerra_mutexacquirer_init (CinelerraMutexacquirer self, CinelerraMutex mutex, return self; } + /** * lock the mutex. * must not already be locked @@ -118,12 +135,51 @@ cinelerra_mutexacquirer_lock (CinelerraMutexacquirer self) } +/** + * get the state of a lock. + * @param self mutexacquirer associated with a mutex variable + * @return CINELERRA_LOCKED when the mutex is locked by this thead + */ +static inline enum cinelerra_lockstate +cinelerra_mutexacquirer_state (CinelerraMutexacquirer self) +{ + REQUIRE (self); + return self->state; +} + + +/** + * try to lock a mutex. + * must not already be locked + * @param self mutexacquirer associated with a mutex variable + * @param mutex pointer to a mutex which should be tried + * @return CINELERRA_LOCKED when the mutex got locked + */ +static inline enum cinelerra_lockstate +cinelerra_mutexacquirer_try_mutex (CinelerraMutexacquirer self, CinelerraMutex mutex) +{ + REQUIRE (self); + REQUIRE (self->state == CINELERRA_UNLOCKED, "mutex already locked"); + + self->mutex=mutex; + switch (pthread_mutex_trylock (&self->mutex->mutex)) + { + case 0: + return self->state = CINELERRA_LOCKED; + case EBUSY: + return CINELERRA_UNLOCKED; + default: + CINELERRA_DIE; + } +} + + /** * release mutex. * a mutexacquirer must be unlocked before leaving scope * @param self mutexacquirer associated with a mutex variable */ -static inline int +static inline void cinelerra_mutexacquirer_unlock (CinelerraMutexacquirer self) { REQUIRE (self); diff --git a/src/lib/smartref.h b/src/lib/smartref.h deleted file mode 100644 index 4d200cdc3..000000000 --- a/src/lib/smartref.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - smartref.h - smart and weak references - - Copyright (C) CinelerraCV - 2007, 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 CINELERRA_SMARTREF_H -#define CINELERRA_SMARTREF_H - -#include - -typedef struct cinelerra_reftarget_struct cinelerra_reftarget; -typedef cinelerra_reftarget* CinelerraReftarget; - -typedef struct cinelerra_reference_struct cinelerra_reference; -typedef cinelerra_reference* CinelerraReference; - -#include "lib/mutex.h" -#include "lib/llist.h" - -/** - * @file Smart and Weak references - * Smart references keep some object alive while they exxisting - * Weak references become invalidated when the referenced object gets destroyed - */ - -/** - * - */ - -struct cinelerra_reftarget_struct -{ - void* object; - void (*dtor)(void*); - cinelerra_mutex lock; - llist smartrefs; - llist weakrefs; -}; - - -CinelerraReftarget -cinelerra_reftarget_init (CinelerraReftarget self, void* obj, void (*dtor)(void*)) -{ - cinelerra_mutex_init (&self->lock); - llist_init (&self->smartrefs); - llist_init (&self->weakrefs); - self->object = obj; - self->dtor = dtor; - return self; -} - -CinelerraReftarget -cinelerra_reftarget_destroy (CinelerraReftarget self) -{ - // lock - // check smartrefs empty else error! - // invalidate weakrefs - // unlock and destroy mutex - // if dtor -> call dtor - return self; -} - - -/** - * - */ - -struct cinelerra_reference_struct -{ - cinelerra_mutex lock; - CinelerraReftarget target; - llist node; -}; - -/* helper function for nobug */ -static inline void -cinelerra_reference_ensureunlinked (CinelerraReference self) -{ - ENSURE (llist_is_empty (&self->node), "forgot to destroy reference"); -} - -/* override with a macro to use the cleanup checker */ -#define cinelerra_reference \ -cinelerra_reference NOBUG_CLEANUP(cinelerra_reference_ensureunlinked) - - -/** - * - */ - -CinelerraReference -cinelerra_smartref_init (CinelerraReference self, CinelerraReftarget target) -{ - cinelerra_mutex_init (&self->lock); - llist_init (&self->node); - self->target = target; - - cinelerra_mutexacquirer l; - cinelerra_mutexacquirer_init_mutex (&l, &target->lock, CINELERRA_LOCKED); - llist_insert_tail (&target->smartrefs, &self->node); - cinelerra_mutexacquirer_unlock (&l); - return self; -} - -CinelerraReference -cinelerra_smartref_destroy (CinelerraReference self) -{ - cinelerra_mutexacquirer l; - cinelerra_mutexacquirer_init_mutex (&l, &self->target->lock, CINELERRA_LOCKED); - llist_unlink (&self->node); - CinelerraReftarget tmp = self->target; - self->target = NULL; - cinelerra_mutexacquirer_unlock (&l); - - cinelerra_mutex_destroy (&self->lock); - return self; -} - -void* -cinelerra_smartref_get (CinelerraReference self, CinelerraMutexacquirer lock) -{ - cinelerra_mutexacquirer_init_mutex (lock, &self->lock, CINELERRA_LOCKED); - return self->target->object; -} - -/** - * - */ - -CinelerraReference -cinelerra_weakref_init (CinelerraReference self, CinelerraReftarget target) -{ - cinelerra_mutex_init (&self->lock); - llist_init (&self->node); - self->target = target; - - cinelerra_mutexacquirer l; - cinelerra_mutexacquirer_init_mutex (&l, &target->lock, CINELERRA_LOCKED); - llist_insert_tail (&target->weakrefs, &self->node); - cinelerra_mutexacquirer_unlock (&l); - return self; -} - -CinelerraReference -cinelerra_weakref_destroy (CinelerraReference self) -{ - //cinelerra_mutexacquirer l; - //cinelerra_mutexacquirer_init_mutex (&l, &self->target->lock, CINELERRA_LOCKED); - //llist_unlink (&self->node); - //self->target = NULL; - //cinelerra_mutexacquirer_unlock (&l); - - //cinelerra_mutex_destroy (&self->lock); - return self; -} - -void* -cinelerra_weakref_get (CinelerraReference self, CinelerraMutexacquirer lock) -{ - cinelerra_mutexacquirer_init_mutex (lock, &self->lock, CINELERRA_LOCKED); - return self->target? self->target->object : NULL; -} - - - -#endif diff --git a/tests/locking/mutex.c b/tests/locking/mutex.c index af4b563d9..3e9b58d8e 100644 --- a/tests/locking/mutex.c +++ b/tests/locking/mutex.c @@ -27,6 +27,6 @@ int mutexforgotunlock() cinelerra_mutex_init (&m); cinelerra_mutexacquirer l; - cinelerra_mutexacquirer_init (&l, &m, CINELERRA_LOCKED); + cinelerra_mutexacquirer_init_mutex (&l, &m, CINELERRA_LOCKED); return 0; }