Skip to content

Instantly share code, notes, and snippets.

@BuonOmo
Last active September 12, 2022 08:32
Show Gist options
  • Select an option

  • Save BuonOmo/a4467a2701920625d40f4461749ef0f1 to your computer and use it in GitHub Desktop.

Select an option

Save BuonOmo/a4467a2701920625d40f4461749ef0f1 to your computer and use it in GitHub Desktop.

Revisions

  1. BuonOmo renamed this gist Sep 12, 2022. 1 changed file with 15 additions and 13 deletions.
    28 changes: 15 additions & 13 deletions shared_ptr.c → shared_ptr.h
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@
    #ifndef SHARED_PTR_H
    #define SHARED_PTR_H

    #include <stdlib.h>
    #include <stdio.h>
    #include <stdatomic.h>
    @@ -12,10 +15,10 @@

    typedef struct shared_ptr shared_ptr;

    shared_ptr* sp_new(void **obj, void (*free_fn)(void *));
    shared_ptr* sp_copy(const shared_ptr *sp);
    void sp_free(shared_ptr *sp);
    void *sp_get(const shared_ptr *sp);
    shared_ptr* sp_new(void **obj, void (*free_fn)(void *));
    shared_ptr* sp_copy(const shared_ptr *sp);
    void sp_free(shared_ptr *sp);
    void* sp_get(const shared_ptr *sp);

    /* Implementation */

    @@ -51,10 +54,9 @@ struct shared_ptr {
    inner_ptr *ptr;
    };


    shared_ptr* sp_new(void **obj, void (*free_fn)(void *)) {
    shared_ptr *sp = malloc(sizeof(shared_ptr));
    sp->ptr = malloc(sizeof(inner_ptr));
    shared_ptr *sp = (shared_ptr*)malloc(sizeof(shared_ptr));
    sp->ptr = (inner_ptr*)malloc(sizeof(inner_ptr));
    sp->ptr->count = 1;
    sp->ptr->obj = *obj;
    sp->ptr->free_fn = free_fn;
    @@ -64,7 +66,7 @@ shared_ptr* sp_new(void **obj, void (*free_fn)(void *)) {

    shared_ptr* sp_copy(const shared_ptr *sp) {
    atomic_fetch_add(&sp->ptr->count, 1);
    shared_ptr *new_sp = malloc(sizeof(shared_ptr));
    shared_ptr *new_sp = (shared_ptr*)malloc(sizeof(shared_ptr));
    new_sp->ptr = sp->ptr;
    return new_sp;
    }
    @@ -77,15 +79,15 @@ void sp_free(shared_ptr *sp) {
    free(sp);
    }

    void *sp_get(const shared_ptr *sp) {
    void* sp_get(const shared_ptr *sp) {
    return sp->ptr->obj;
    }

    /* Example */

    #ifdef TEST
    int main(int argc, char const *argv[])
    {
    #ifdef TEST
    obj *o = malloc(sizeof(struct obj));
    char *str = "Hello World";
    o->content = str;
    @@ -108,9 +110,9 @@ int main(int argc, char const *argv[])
    assert(malloc_count == free_count);

    printf("tests passed\n");
    #else
    printf("please define TEST to test\n");
    #endif

    return 0;
    }
    #endif

    #endif // SHARED_PTR_H
  2. BuonOmo revised this gist Aug 23, 2022. 1 changed file with 21 additions and 16 deletions.
    37 changes: 21 additions & 16 deletions shared_ptr.c
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,12 @@
    #include <stdio.h>
    #include <stdatomic.h>

    #ifdef TEST
    #include <assert.h>
    #include <string.h>
    #define streq(a, b) (!strcmp((a), (b)))
    #endif

    /* API */

    typedef struct shared_ptr shared_ptr;
    @@ -13,9 +19,7 @@ void *sp_get(const shared_ptr *sp);

    /* Implementation */

    // #define ALLOC_TEST

    #ifdef ALLOC_TEST
    #ifdef TEST
    int malloc_count = 0;
    int free_count = 0;

    @@ -79,33 +83,34 @@ void *sp_get(const shared_ptr *sp) {

    /* Example */


    int main(int argc, char const *argv[])
    {
    #ifdef TEST
    obj *o = malloc(sizeof(struct obj));
    o->content = "Hello World";
    char *str = "Hello World";
    o->content = str;

    shared_ptr *sp = sp_new((void **)&o, free);
    if (o == NULL) {
    printf("cool\n");
    }

    printf("%s\n", ((obj*)(sp_get(sp)))->content);
    assert(o == NULL);
    assert(streq(str, ((obj*)(sp_get(sp)))->content));

    shared_ptr *sp2 = sp_copy(sp);

    printf("%s\n", ((obj*)(sp_get(sp2)))->content);
    printf("%s\n", ((obj*)(sp_get(sp)))->content);
    assert(streq(str, ((obj*)(sp_get(sp2)))->content));
    assert(streq(str, ((obj*)(sp_get(sp)))->content));

    sp_free(sp2);

    printf("%s\n", ((obj*)(sp_get(sp)))->content);
    assert(streq(str, ((obj*)(sp_get(sp)))->content));

    sp_free(sp);

    #ifdef ALLOC_TEST
    printf("mallocs: %d\n", malloc_count);
    printf("frees: %d\n", free_count);
    assert(malloc_count == free_count);

    printf("tests passed\n");
    #else
    printf("please define TEST to test\n");
    #endif

    return 0;
    }
  3. BuonOmo revised this gist Aug 11, 2022. 1 changed file with 18 additions and 5 deletions.
    23 changes: 18 additions & 5 deletions shared_ptr.c
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,17 @@
    #include <stdio.h>
    #include <stdatomic.h>

    /* API */

    typedef struct shared_ptr shared_ptr;

    shared_ptr* sp_new(void **obj, void (*free_fn)(void *));
    shared_ptr* sp_copy(const shared_ptr *sp);
    void sp_free(shared_ptr *sp);
    void *sp_get(const shared_ptr *sp);

    /* Implementation */

    // #define ALLOC_TEST

    #ifdef ALLOC_TEST
    @@ -32,12 +43,12 @@ typedef struct inner_ptr {
    void (*free_fn)(void *);
    } inner_ptr;

    typedef struct shared_ptr {
    struct shared_ptr {
    inner_ptr *ptr;
    } shared_ptr;
    };


    shared_ptr* sp_new(obj **obj, void (*free_fn)(void *)) {
    shared_ptr* sp_new(void **obj, void (*free_fn)(void *)) {
    shared_ptr *sp = malloc(sizeof(shared_ptr));
    sp->ptr = malloc(sizeof(inner_ptr));
    sp->ptr->count = 1;
    @@ -62,17 +73,19 @@ void sp_free(shared_ptr *sp) {
    free(sp);
    }

    void *sp_get(shared_ptr *sp) {
    void *sp_get(const shared_ptr *sp) {
    return sp->ptr->obj;
    }

    /* Example */


    int main(int argc, char const *argv[])
    {
    obj *o = malloc(sizeof(struct obj));
    o->content = "Hello World";

    shared_ptr *sp = sp_new(&o, free);
    shared_ptr *sp = sp_new((void **)&o, free);
    if (o == NULL) {
    printf("cool\n");
    }
  4. BuonOmo created this gist Aug 11, 2022.
    98 changes: 98 additions & 0 deletions shared_ptr.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdatomic.h>

    // #define ALLOC_TEST

    #ifdef ALLOC_TEST
    int malloc_count = 0;
    int free_count = 0;

    void *_malloc(size_t size) {
    malloc_count++;
    return malloc(size);
    }

    void _free(void *ptr) {
    free_count++;
    free(ptr);
    }

    #define malloc _malloc
    #define free _free
    #endif

    typedef struct obj {
    char *content;
    } obj;

    typedef struct inner_ptr {
    _Atomic int count;
    void *obj;
    void (*free_fn)(void *);
    } inner_ptr;

    typedef struct shared_ptr {
    inner_ptr *ptr;
    } shared_ptr;


    shared_ptr* sp_new(obj **obj, void (*free_fn)(void *)) {
    shared_ptr *sp = malloc(sizeof(shared_ptr));
    sp->ptr = malloc(sizeof(inner_ptr));
    sp->ptr->count = 1;
    sp->ptr->obj = *obj;
    sp->ptr->free_fn = free_fn;
    *obj = NULL;
    return sp;
    }

    shared_ptr* sp_copy(const shared_ptr *sp) {
    atomic_fetch_add(&sp->ptr->count, 1);
    shared_ptr *new_sp = malloc(sizeof(shared_ptr));
    new_sp->ptr = sp->ptr;
    return new_sp;
    }

    void sp_free(shared_ptr *sp) {
    if (atomic_fetch_sub(&sp->ptr->count, 1) == 1) {
    sp->ptr->free_fn(sp->ptr->obj);
    free(sp->ptr);
    }
    free(sp);
    }

    void *sp_get(shared_ptr *sp) {
    return sp->ptr->obj;
    }


    int main(int argc, char const *argv[])
    {
    obj *o = malloc(sizeof(struct obj));
    o->content = "Hello World";

    shared_ptr *sp = sp_new(&o, free);
    if (o == NULL) {
    printf("cool\n");
    }

    printf("%s\n", ((obj*)(sp_get(sp)))->content);

    shared_ptr *sp2 = sp_copy(sp);

    printf("%s\n", ((obj*)(sp_get(sp2)))->content);
    printf("%s\n", ((obj*)(sp_get(sp)))->content);

    sp_free(sp2);

    printf("%s\n", ((obj*)(sp_get(sp)))->content);

    sp_free(sp);

    #ifdef ALLOC_TEST
    printf("mallocs: %d\n", malloc_count);
    printf("frees: %d\n", free_count);
    #endif
    return 0;
    }