Fixing calls to destructors in OBJ_RELEASE
Also preparing for move to BSD-based atomic operations. This commit was SVN r811.
Этот коммит содержится в:
родитель
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user