1
1

Fixing calls to destructors in OBJ_RELEASE

Also preparing for move to BSD-based atomic operations.

This commit was SVN r811.
Этот коммит содержится в:
David Daniel 2004-02-18 06:09:58 +00:00
родитель edf0669882
Коммит 85558e92d4

Просмотреть файл

@ -103,9 +103,9 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include "lam_config.h" #include "lam_config.h"
#include "lam/types.h" #endif
#include "lam/atomic.h"
/* /*
* BEGIN_C_DECLS should be used at the beginning of your declarations, * BEGIN_C_DECLS should be used at the beginning of your declarations,
@ -184,9 +184,12 @@
*/ */
#define OBJ_RETAIN(object) \ #define OBJ_RETAIN(object) \
do { \ do { \
assert(NULL != object); \
assert(NULL != ((lam_object_t *) object)->obj_class); \
if (object) { \ if (object) { \
lam_obj_retain((lam_object_t *) object); \ lam_obj_update((lam_object_t *) object, 1); \
} \ } \
assert(((lam_object_t *) object)->obj_reference_count >= 0); \
} while (0) } while (0)
@ -195,12 +198,19 @@
* reference count reaches zero, destruct (finalize) the object and * reference count reaches zero, destruct (finalize) the object and
* free its storage. * free its storage.
* *
* Note: If the object is freed, then the value of the pointer is set
* to NULL.
*
* @param object Pointer to the object * @param object Pointer to the object
*/ */
#define OBJ_RELEASE(object) \ #define OBJ_RELEASE(object) \
do { \ do { \
if (object) { \ assert(NULL != object); \
lam_obj_release((lam_object_t *) object); \ assert(NULL != ((lam_object_t *) object)->obj_class); \
if (0 == lam_obj_update((lam_object_t *) object, -1)) { \
lam_obj_run_destructors((lam_object_t *) object); \
free(object); \
object = NULL; \
} \ } \
} while (0) } while (0)
@ -380,50 +390,35 @@ static inline lam_object_t *lam_obj_new(size_t size,
} }
/* static inline int lam_atomic_cmpset_int(int *addr, int oldval, int newval)
* This function is used by inline functions later in this file, and
* it must be defined by other header files later (eg., one of the
* atomic.h's).
*/
static inline int fetchNadd(volatile int *addr, int inc);
/**
* Retain an object (by incrementing its reference count)
*
* Do not use this function directly: use OBJ_RETAIN instead.
*
* @param object Pointer to the object
*/
static inline void lam_obj_retain(lam_object_t *object)
{ {
assert(NULL != object); *addr = newval;
assert(NULL != object->obj_class); return 1;
fetchNadd(&(object->obj_reference_count), 1);
assert(object->obj_reference_count >= 0);
} }
/** /**
* Release an object (by decrementing its reference count). If the * Atomically update the object's reference count by some increment.
* reference count reaches zero, destruct (finalize) the object and
* free its storage.
* *
* Do not use this function directly: use OBJ_RELEASE instead. * This function should not be used directly: it is called via the
* macros OBJ_RETAIN and OBJ_RELEASE
* *
* @param object Pointer to the object * @param object Pointer to the object
* @param inc Increment by which to update reference count
* @return New value of the reference count
*/ */
static inline void lam_obj_release(lam_object_t *object) static inline int lam_obj_update(lam_object_t *object, int inc)
{ {
assert(NULL != object); int oldval;
assert(NULL != object->obj_class); int newval;
int *addr;
if (fetchNadd(&object->obj_reference_count, -1) == 1) { addr = &(object->obj_reference_count);
object->obj_class->cls_destruct(object); do {
free(object); oldval = *addr;
} newval = oldval + inc;
} while (lam_atomic_cmpset_int(addr, oldval, newval) != 0);
return newval;
} }
/**********************************************************************/ /**********************************************************************/