From 7f7a2fb4fb23433e7be3d6953725690c8ea958d2 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 Aug 2026 19:44:56 +0000 Subject: The objects returned to the user are now integer-based references, not actual pointers. This means the aplwc internals can update those pointers without the user noticing. FossilOrigin-Name: 654c7d0ec85da295a7fb6ed381500410686b280f342fa81a30481f5e9a20c58a --- src/lib/memory.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) (limited to 'src/lib/memory.c') diff --git a/src/lib/memory.c b/src/lib/memory.c index 8a91d2d..b6e044a 100644 --- a/src/lib/memory.c +++ b/src/lib/memory.c @@ -26,6 +26,7 @@ memory_init(struct aplwc *aplwc) aplwc->unaligned_data = NULL; aplwc->size = 0; aplwc->memptrs = NULL; + aplwc->rootptrs = NULL; } void @@ -49,6 +50,7 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old) struct chunk *c; struct memory_ptr_frame *frame; + struct root_ptr *root; size_t add, sub, i; if(new > old){ @@ -89,6 +91,10 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old) for(i = 0; i < frame->count; i++) if(frame->ptrs[i]) FIX(*frame->ptrs[i]); + + for(root = aplwc->rootptrs; root; root = root->link) + if(root->ptr) + FIX(root->ptr); #undef FIX #undef FIX_DATA @@ -198,13 +204,71 @@ retry: return new->data; } +struct aplwc_ref +memory_root_new(struct aplwc *aplwc, void *p) +{ + struct aplwc_ref ref; + struct root_ptr *root; + size_t size; + + clear_ref(&ref); + if(aplwc->fns.alloc == NULL){ + aplwc->last_error = APLWC_OUT_OF_MEMORY; + goto end; + } + + root = aplwc->fns.alloc(sizeof(*root), sizeof(*root), &size); + if(root == NULL){ + aplwc->last_error = APLWC_OUT_OF_MEMORY; + goto end; + } + + root->id = aplwc->rootptrs ? (aplwc->rootptrs->id+1) : 0; + root->ptr = p; + root->link = aplwc->rootptrs; + aplwc->rootptrs = root; + + ref.id = root->id; + ref.aplwc = aplwc; +end: + return ref; +} + +void * +memory_root_get(struct aplwc_ref ref) +{ + struct root_ptr *root; + + if(!valid_ref(ref)) + return NULL; + + for(root = ref.aplwc->rootptrs; root; root = root->link) + if(root->id == ref.id) + return root->ptr; + + return NULL; +} + void -memory_free_root(struct aplwc *aplwc, void *p) +memory_root_free(struct aplwc_ref ref) { - if(NEVER(p == NULL)) + struct aplwc *aplwc; + struct root_ptr **root, *tmp; + + if(!valid_ref(ref)) return; - UNUSED_PARAMETER(aplwc); + aplwc = ref.aplwc; + + for(root = &aplwc->rootptrs; (*root); root = &(*root)->link){ + if((*root)->id == ref.id){ + tmp = *root; + *root = tmp->link; + if(aplwc->fns.dealloc) + aplwc->fns.dealloc(tmp); + break; + } + } } void @@ -273,3 +337,16 @@ memory_alloc_aplwc_module(struct aplwc *aplwc) p = alloc(aplwc, sizeof(struct aplwc_module), CHUNK_TAG_APLWC_MODULE); return p; } + +void +clear_ref(struct aplwc_ref *ref) +{ + ref->id = -1; + ref->aplwc = NULL; +} + +int +valid_ref(struct aplwc_ref ref) +{ + return ref.id >= 0; +} -- cgit v1.2.3