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

View File

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

View File

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