Add void_obj option
This commit is contained in:
@ -51,6 +51,8 @@ typedef void (*refcount_destroy_callback_t)(void *obj, void *user_data);
|
|||||||
*/
|
*/
|
||||||
typedef struct RefcountContext {
|
typedef struct RefcountContext {
|
||||||
size_t entry_offset; //!< Offset to the #RefcountEntry member.
|
size_t entry_offset; //!< Offset to the #RefcountEntry member.
|
||||||
|
void *void_val; //!< Value returned by #refcount_context_unref when a
|
||||||
|
//!< reference count falls to 0.
|
||||||
refcount_held_refs_callback_t
|
refcount_held_refs_callback_t
|
||||||
held_refs_callback; //!< Callback to list an object's held references.
|
held_refs_callback; //!< Callback to list an object's held references.
|
||||||
refcount_destroy_callback_t
|
refcount_destroy_callback_t
|
||||||
@ -75,7 +77,7 @@ typedef struct RefcountContext {
|
|||||||
extern RefcountContext *refcount_default_context;
|
extern RefcountContext *refcount_default_context;
|
||||||
|
|
||||||
RefcountContext *
|
RefcountContext *
|
||||||
refcount_make_context(size_t entry_offset,
|
refcount_make_context(size_t entry_offset, void *void_val,
|
||||||
refcount_held_refs_callback_t held_refs_callback,
|
refcount_held_refs_callback_t held_refs_callback,
|
||||||
refcount_destroy_callback_t destroy_callback,
|
refcount_destroy_callback_t destroy_callback,
|
||||||
void *user_data, const RefcountAllocator *alloc);
|
void *user_data, const RefcountAllocator *alloc);
|
||||||
|
@ -59,7 +59,7 @@ RefcountContext *refcount_default_context = NULL;
|
|||||||
* @return The new context, or NULL in the case of an error
|
* @return The new context, or NULL in the case of an error
|
||||||
*/
|
*/
|
||||||
RefcountContext *
|
RefcountContext *
|
||||||
refcount_make_context(size_t entry_offset,
|
refcount_make_context(size_t entry_offset, void *void_val,
|
||||||
refcount_held_refs_callback_t held_refs_callback,
|
refcount_held_refs_callback_t held_refs_callback,
|
||||||
refcount_destroy_callback_t destroy_callback,
|
refcount_destroy_callback_t destroy_callback,
|
||||||
void *user_data, const RefcountAllocator *alloc) {
|
void *user_data, const RefcountAllocator *alloc) {
|
||||||
@ -82,6 +82,7 @@ refcount_make_context(size_t entry_offset,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ctx->entry_offset = entry_offset;
|
ctx->entry_offset = entry_offset;
|
||||||
|
ctx->void_val = void_val;
|
||||||
ctx->held_refs_callback = held_refs_callback;
|
ctx->held_refs_callback = held_refs_callback;
|
||||||
ctx->destroy_callback = destroy_callback;
|
ctx->destroy_callback = destroy_callback;
|
||||||
ctx->user_data = user_data;
|
ctx->user_data = user_data;
|
||||||
@ -355,7 +356,7 @@ end:
|
|||||||
*/
|
*/
|
||||||
void *refcount_context_ref(const RefcountContext *ctx, void *obj) {
|
void *refcount_context_ref(const RefcountContext *ctx, void *obj) {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return NULL;
|
return ctx->void_val;
|
||||||
}
|
}
|
||||||
if (!lock_entry_mtx(ENTRY)) {
|
if (!lock_entry_mtx(ENTRY)) {
|
||||||
return obj;
|
return obj;
|
||||||
@ -419,7 +420,7 @@ static void remove_gc_root(RefcountContext *ctx, void *obj) {
|
|||||||
static void *unref_to_queue(RefcountContext *ctx, void *obj,
|
static void *unref_to_queue(RefcountContext *ctx, void *obj,
|
||||||
RefcountList **queue) {
|
RefcountList **queue) {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return NULL;
|
return ctx->void_val;
|
||||||
} else if (ENTRY->is_static) {
|
} else if (ENTRY->is_static) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -437,7 +438,7 @@ static void *unref_to_queue(RefcountContext *ctx, void *obj,
|
|||||||
*queue = refcount_list_push_full(*queue, obj, &ctx->alloc);
|
*queue = refcount_list_push_full(*queue, obj, &ctx->alloc);
|
||||||
}
|
}
|
||||||
unlock_entry_mtx(ENTRY);
|
unlock_entry_mtx(ENTRY);
|
||||||
return NULL;
|
return ctx->void_val;
|
||||||
} else {
|
} else {
|
||||||
--ENTRY->impl.counted.ref_count;
|
--ENTRY->impl.counted.ref_count;
|
||||||
track_gc_root(ctx, obj);
|
track_gc_root(ctx, obj);
|
||||||
@ -523,7 +524,7 @@ static void process_unref_queue(RefcountContext *ctx, RefcountList *queue,
|
|||||||
*/
|
*/
|
||||||
void *refcount_context_unref(RefcountContext *ctx, void *obj) {
|
void *refcount_context_unref(RefcountContext *ctx, void *obj) {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return NULL;
|
return ctx->void_val;
|
||||||
}
|
}
|
||||||
RefcountList *queue = NULL;
|
RefcountList *queue = NULL;
|
||||||
void *retval = unref_to_queue(ctx, obj, &queue);
|
void *retval = unref_to_queue(ctx, obj, &queue);
|
||||||
|
@ -50,7 +50,7 @@ int main(int argc, const char **argv) {
|
|||||||
struct ContextAndFlag ctx_and_flag = {.should_be_doing_gc = false};
|
struct ContextAndFlag ctx_and_flag = {.should_be_doing_gc = false};
|
||||||
|
|
||||||
RefcountContext *c = refcount_make_context(
|
RefcountContext *c = refcount_make_context(
|
||||||
offsetof(A, refcount), held_refs_callback, destroy_callback,
|
offsetof(A, refcount), NULL, held_refs_callback, destroy_callback,
|
||||||
&ctx_and_flag, &COUNTING_ALLOCATOR);
|
&ctx_and_flag, &COUNTING_ALLOCATOR);
|
||||||
|
|
||||||
ctx_and_flag.ctx = c;
|
ctx_and_flag.ctx = c;
|
||||||
|
Reference in New Issue
Block a user