diff --git a/include/refcount/refcount.h b/include/refcount/refcount.h index e19e031..7d4cb06 100644 --- a/include/refcount/refcount.h +++ b/include/refcount/refcount.h @@ -51,6 +51,8 @@ typedef void (*refcount_destroy_callback_t)(void *obj, void *user_data); */ typedef struct RefcountContext { 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 held_refs_callback; //!< Callback to list an object's held references. refcount_destroy_callback_t @@ -75,7 +77,7 @@ typedef struct RefcountContext { extern RefcountContext *refcount_default_context; 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_destroy_callback_t destroy_callback, void *user_data, const RefcountAllocator *alloc); diff --git a/src/refcount.c b/src/refcount.c index 2292ae9..ad42a50 100644 --- a/src/refcount.c +++ b/src/refcount.c @@ -59,7 +59,7 @@ RefcountContext *refcount_default_context = NULL; * @return The new context, or NULL in the case of an error */ 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_destroy_callback_t destroy_callback, void *user_data, const RefcountAllocator *alloc) { @@ -82,6 +82,7 @@ refcount_make_context(size_t entry_offset, } #endif ctx->entry_offset = entry_offset; + ctx->void_val = void_val; ctx->held_refs_callback = held_refs_callback; ctx->destroy_callback = destroy_callback; ctx->user_data = user_data; @@ -355,7 +356,7 @@ end: */ void *refcount_context_ref(const RefcountContext *ctx, void *obj) { if (!obj) { - return NULL; + return ctx->void_val; } if (!lock_entry_mtx(ENTRY)) { return obj; @@ -419,7 +420,7 @@ static void remove_gc_root(RefcountContext *ctx, void *obj) { static void *unref_to_queue(RefcountContext *ctx, void *obj, RefcountList **queue) { if (!obj) { - return NULL; + return ctx->void_val; } else if (ENTRY->is_static) { return obj; } @@ -437,7 +438,7 @@ static void *unref_to_queue(RefcountContext *ctx, void *obj, *queue = refcount_list_push_full(*queue, obj, &ctx->alloc); } unlock_entry_mtx(ENTRY); - return NULL; + return ctx->void_val; } else { --ENTRY->impl.counted.ref_count; 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) { if (!obj) { - return NULL; + return ctx->void_val; } RefcountList *queue = NULL; void *retval = unref_to_queue(ctx, obj, &queue); diff --git a/test/test_refcount.c b/test/test_refcount.c index fcbf921..382c75b 100644 --- a/test/test_refcount.c +++ b/test/test_refcount.c @@ -50,7 +50,7 @@ int main(int argc, const char **argv) { struct ContextAndFlag ctx_and_flag = {.should_be_doing_gc = false}; 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.ctx = c;