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.
Simple shared pointer lib in C
#include <stdlib.h>
#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
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;
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));
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(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((void **)&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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment