Add void_obj option

This commit is contained in:
2025-09-09 15:13:23 -07:00
parent 403618888c
commit 5064f304ca
3 changed files with 10 additions and 7 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;