libabacus/include/refcount.h

148 lines
3.8 KiB
C

#ifndef LIBABACUS_REFCOUNT_H
#define LIBABACUS_REFCOUNT_H
#include "result.h"
struct libab_ref_s;
struct libab_ref_count_s;
typedef void (*libab_visitor_function_ptr)(struct libab_ref_count_s* , void*);
typedef void (*libab_visit_function_ptr)(void*, libab_visitor_function_ptr, void*);
/**
* A struct for holding
* the number of references
* to a value, as well as the function required
* to free the value.
*/
struct libab_ref_count_s {
/**
* The value this reference holds.
*/
void* data;
/**
* The fucntion to free the value.
* Can be NULL for no-op.
*/
void (*free_func)(void* data);
/**
* The number of references that
* prevent the deallocation of the value.
*/
int strong;
/**
* The number of references
* that still exist, even to a freed instance.
*/
int weak;
/**
* The number of outside references.
* This is used for garbage collection.
*/
int gc;
/**
* Previous pointer for garbage collection
* linked list.
*/
struct libab_ref_count_s* prev;
/**
* Next pointer for garbage collection
* linked list.
*/
struct libab_ref_count_s* next;
/**
* Function used to visit child containers,
* used by GC.
*/
libab_visit_function_ptr visit_children;
};
/**
* Struct used to create an interface
* for a set of objects to be collected.
*/
struct libab_ref_gc_list_s {
/**
* The head of the linked list.
*/
struct libab_ref_count_s* head;
/**
* The tail of the linked list.
*/
struct libab_ref_count_s* tail;
};
/**
* A reference to a value.
*/
struct libab_ref_s {
/**
* Whether this reference is a strong reference.
*/
unsigned int strong : 1;
/**
* Whether this reference is a NULL reference.
*/
unsigned int null : 1;
/**
* The reference count struct keeping track
* of how many references are pointing to the value.
*/
struct libab_ref_count_s* count;
};
typedef struct libab_ref_s libab_ref;
typedef struct libab_ref_count_s libab_ref_count;
typedef struct libab_ref_gc_list_s libab_ref_gc_list;
/**
* Creates a new referene, using the given data and free function.
* @param ref the reference to initialize with the given data.
* @param data the data to reference count.
* @param free_func the function to use to realease the data when refcount
* reaches 0.
* @return the result of the construction of the reference.
*/
libab_result libab_ref_new(libab_ref* ref, void* data,
void (*free_func)(void* data));
/**
* Creates a reference to NULL. This does
* not require a memory allocation.
* @param ref the reference to initialize with null.
*/
void libab_ref_null(libab_ref* ref);
void libab_ref_gc_visit(libab_ref*, libab_visitor_function_ptr visitor, void*);
void libab_ref_gc_add(libab_ref* ref,
libab_visit_function_ptr visit_children,
libab_ref_gc_list* list);
void libab_ref_gc_run(libab_ref_gc_list* list);
/**
* Turns the given reference into a weak reference,
* making it not keep the data allocated.
*/
void libab_ref_weaken(libab_ref* ref);
/**
* Releases this particular reference to the data.
* This doesn't necessarily free the underlying data.
*/
void libab_ref_free(libab_ref* ref);
/**
* Copies this reference, thereby increasing the reference count.
*/
void libab_ref_copy(const libab_ref* ref, libab_ref* into);
/**
* Swaps the contents of two references.
*/
void libab_ref_swap(libab_ref* left, libab_ref* right);
/**
* Function that can be passed in to refcount to simply use free
* when the refcount reaches 0.
*/
void libab_ref_data_free(void*);
/**
* Gets the value of the reference.
*/
void* libab_ref_get(const libab_ref* ref);
#endif