smartref.h WIP
This commit is contained in:
parent
65ce98c87d
commit
38ce0afec4
1 changed files with 181 additions and 0 deletions
181
src/lib/smartref.h
Normal file
181
src/lib/smartref.h
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
smartref.h - smart and weak references
|
||||||
|
|
||||||
|
Copyright (C) CinelerraCV
|
||||||
|
2007, 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 CINELERRA_SMARTREF_H
|
||||||
|
#define CINELERRA_SMARTREF_H
|
||||||
|
|
||||||
|
#include <nobug.h>
|
||||||
|
|
||||||
|
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
|
||||||
Loading…
Reference in a new issue