From: patrick-scho Date: Fri, 30 May 2025 20:57:39 +0000 (+0200) Subject: add smartptrs.c X-Git-Url: https://gitweb.ps.run/onefile/commitdiff_plain/a2edaafd70170e4a8973f784dd8cb1f0762f4b85 add smartptrs.c --- diff --git a/smartptrs.c b/smartptrs.c new file mode 100644 index 0000000..fb483ec --- /dev/null +++ b/smartptrs.c @@ -0,0 +1,178 @@ +#include +#include +#include + +typedef struct Ptr *Ptr; +typedef struct Ref *Ref; + +typedef struct Ptr +{ + Ref ref; + Ptr next, prev; +} *Ptr; +typedef struct Ref +{ + int *data; + Ptr head, tail; +} *Ref; + +Ref ref_new(int value) +{ + Ref result = malloc(sizeof(struct Ref)); + + result->data = malloc(sizeof(int)); + *result->data = value; + + result->head = result->tail = NULL; + + return result; +} + +Ref ref_move(Ref ref) +{ + Ref result = malloc(sizeof(struct Ref)); + + result->data = ref->data; + + result->head = ref->head; + result->tail = ref->tail; + + for (Ptr p = ref->head; p != NULL; p = p->next) + { + p->ref = result; + } + free(ref); + return result; +} + +void ref_add_ptr(Ref ref, Ptr ptr) +{ + if (ref->head == NULL) + { + ref->head = ptr; + ref->tail = ptr; + ptr->next = ptr->prev = NULL; + return; + } + ref->tail->next = ptr; + ptr->prev = ref->tail; + ptr->next = NULL; + ref->tail = ptr; +} + +void ref_remove_ptr(Ref ref, Ptr ptr) +{ + for (Ptr p = ref->head; p != NULL; p = p->next) + { + if (p == ptr) + { + if (p->prev == NULL) + ref->head = p->next; + else + p->prev->next = p->next; + + if (p->next == NULL) + ref->tail = p->prev; + else + p->next->prev = p->prev; + + return; + } + } +} + +void ref_free(Ref ref) +{ + for (Ptr p = ref->head; p != NULL; p = p->next) + { + p->ref = NULL; + } + free(ref->data); + free(ref); +} + +Ptr ptr_new(Ref ref) +{ + Ptr result = malloc(sizeof(struct Ptr)); + + result->ref = ref; + + ref_add_ptr(ref, result); + + return result; +} + +int ptr_get(Ptr ptr) +{ + if (ptr->ref != NULL) + return *ptr->ref->data; + return 0; +} + +void ptr_free(Ptr ptr) +{ + if (ptr->ref != NULL) + ref_remove_ptr(ptr->ref, ptr); + free(ptr); +} + +void test_ref() +{ + Ref r1 = ref_new(123); + + Ptr p1 = ptr_new(r1); + Ptr p2 = ptr_new(r1); + Ptr p3 = ptr_new(r1); + Ptr p4 = ptr_new(r1); + + Ref r2 = ref_move(r1); + + int i = ptr_get(p1) + ptr_get(p2) + ptr_get(p3) + ptr_get(p4); + + ptr_free(p1); + ptr_free(p2); + + ref_free(r2); + + ptr_free(p3); + ptr_free(p4); +} + +void test_reg() +{ + int *r1 = malloc(sizeof(int)); + *r1 = 123; + + int *p1 = r1; + int *p2 = r1; + int *p3 = r1; + int *p4 = r1; + + int i = *p1 + *p2 + *p3 + *p4; + + int *r2 = r1; + r1 = NULL; + + free(r2); +} + +int main(int argc, char **argv) +{ + const long N = 1000000; + + clock_t start, end; + + start = clock(); + for (long i = 0; i < N; i++) + test_ref(); + end = clock(); + printf("ref: %fms\n", ((double)(end - start)) / CLOCKS_PER_SEC * 1000); + + start = clock(); + for (long i = 0; i < N; i++) + test_reg(); + end = clock(); + printf("reg: %fms\n", ((double)(end - start)) / CLOCKS_PER_SEC * 1000); + + return 0; +}