Add multi-thread support
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#define INCLUDED_REFCOUNT_ALLOCATOR_H
|
||||
|
||||
#include <ht.h>
|
||||
#include <refcount/config.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
12
include/refcount/config.h.in
Normal file
12
include/refcount/config.h.in
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef INCLUDED_REFCOUNT_CONFIG_H
|
||||
#define INCLUDED_REFCOUNT_CONFIG_H
|
||||
|
||||
#cmakedefine REFCOUNT_HAS_THREADS
|
||||
|
||||
#if defined(REFCOUNT_HAS_THREADS) \
|
||||
&& (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L)
|
||||
# error \
|
||||
"RefCount needs to be compiled with at least C11 for thread support to work."
|
||||
#endif
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
#define INCLUDED_REFCOUNT_LIST_H
|
||||
|
||||
#include <refcount/allocator.h>
|
||||
#include <refcount/config.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
|
@ -5,10 +5,16 @@
|
||||
#define INCLUDED_REFCOUNT_REFCOUNT_H
|
||||
|
||||
#include <ht.h>
|
||||
#include <refcount/config.h>
|
||||
#include <refcount/list.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef REFCOUNT_HAS_THREADS
|
||||
# include <stdatomic.h>
|
||||
# include <threads.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -57,29 +63,12 @@ typedef struct RefcountContext {
|
||||
RefcountList *static_objects; //!< List of static objects registered with
|
||||
//!< this context.
|
||||
RefcountList *gc_roots; //!< List of garbage collector roots.
|
||||
#ifdef REFCOUNT_HAS_THREADS
|
||||
mtx_t so_mtx; //<! Mutex protecting static_objects.
|
||||
mtx_t gr_mtx; //<! Mutex protecting gc_roots.
|
||||
#endif
|
||||
} RefcountContext;
|
||||
|
||||
/**
|
||||
* Enumeration of operations that may cause the debug breakpoint to be called.
|
||||
*/
|
||||
typedef enum {
|
||||
REFCOUNT_OPER_DEINIT_STATIC,
|
||||
REFCOUNT_OPER_FLOAT,
|
||||
} RefcountOperation;
|
||||
|
||||
/**
|
||||
* Type for a function to be called when some kind of error occurs. It should
|
||||
* take a #RefcountOperation, a #RefcountContext pointer, and the object on
|
||||
* which the error occurred.
|
||||
* @param oper The operation that failed
|
||||
* @param ctx The context the operation was performed on
|
||||
* @param obj The object that caused the failure
|
||||
*/
|
||||
typedef void (*refcount_debug_callback_t)(RefcountOperation oper,
|
||||
RefcountContext *ctx, void *obj);
|
||||
|
||||
extern refcount_debug_callback_t refcount_debug_breakpoint;
|
||||
|
||||
extern RefcountContext *refcount_default_context;
|
||||
|
||||
RefcountContext *
|
||||
@ -90,6 +79,20 @@ refcount_make_context(size_t entry_offset,
|
||||
|
||||
void refcount_context_destroy(RefcountContext *ctx);
|
||||
|
||||
/**
|
||||
* Structure holding the required information for a weak reference. That is, a
|
||||
* reference that does not prevent an object from being de-allocated.
|
||||
*/
|
||||
typedef struct RefcountWeakref {
|
||||
#ifdef REFCOUNT_HAS_THREADS
|
||||
_Atomic uint64_t ref_count; //!< Reference count of this weakref (atomic).
|
||||
mtx_t mtx; //!< Mutex protecting both the weakref and it's object.
|
||||
#else
|
||||
uint64_t ref_count; //!< Reference count of this weakref.
|
||||
#endif
|
||||
void *data; //<! The object this weak ref references (not the entry).
|
||||
} RefcountWeakref;
|
||||
|
||||
/**
|
||||
* Opaque struct holding reference data for an object. This should be included
|
||||
* as a non-pointer member of the struct you are trying to track, e.g.
|
||||
@ -103,8 +106,7 @@ void refcount_context_destroy(RefcountContext *ctx);
|
||||
*/
|
||||
typedef struct RefcountEntry {
|
||||
bool is_static; //!< Whether the object is static.
|
||||
RefcountList *weak_refs; //<! List of #RefcountWeakref structures for
|
||||
//<! holding thread safe weak references.
|
||||
RefcountWeakref *weak_ref; //<! Weakref for this entry.
|
||||
union {
|
||||
struct {
|
||||
uint64_t ref_count; //!< The object's reference count.
|
||||
@ -115,16 +117,6 @@ typedef struct RefcountEntry {
|
||||
} impl;
|
||||
} RefcountEntry;
|
||||
|
||||
/**
|
||||
* Structure holding the required information for a weak reference. That is, a
|
||||
* reference that does not prevent an object from being de-allocated.
|
||||
*/
|
||||
typedef struct RefcountWeakref {
|
||||
RefcountList *entry; //!< Link in the #RefcountEntry list of the object this
|
||||
//!< references that points to this reference.
|
||||
void *data; //<! The object this weak ref references (not the entry).
|
||||
} RefcountWeakref;
|
||||
|
||||
/**
|
||||
* Return a pointer to the entry associated with an object.
|
||||
* @param ctx The #RefcountContext
|
||||
@ -154,12 +146,12 @@ static inline bool refcount_context_is_static(const RefcountContext *ctx,
|
||||
* @param obj The object
|
||||
* @return The number of references the object has
|
||||
*/
|
||||
static inline size_t refcount_context_num_refs(const RefcountContext *ctx,
|
||||
void *obj) {
|
||||
static inline uint64_t refcount_context_num_refs(const RefcountContext *ctx,
|
||||
void *obj) {
|
||||
return REFCOUNT_OBJECT_ENTRY(ctx, obj)->impl.counted.ref_count;
|
||||
}
|
||||
|
||||
void refcount_context_init_obj(const RefcountContext *ctx, void *obj);
|
||||
bool refcount_context_init_obj(const RefcountContext *ctx, void *obj);
|
||||
|
||||
bool refcount_context_init_static(RefcountContext *ctx, void *obj);
|
||||
|
||||
@ -199,19 +191,11 @@ RefcountWeakref *refcount_context_make_weakref(const RefcountContext *ctx,
|
||||
void refcount_context_destroy_weakref(const RefcountContext *ctx,
|
||||
RefcountWeakref *wr);
|
||||
|
||||
/**
|
||||
* Return weather the object referenced by a weak reference still exists.
|
||||
* @param ctx The #RefcountContext
|
||||
* @param wr The weak reference
|
||||
* @return Weather the reference is still valid
|
||||
*/
|
||||
static inline bool refcount_context_weakref_is_valid(const RefcountContext *ctx,
|
||||
RefcountWeakref *wr) {
|
||||
return wr->data;
|
||||
}
|
||||
bool refcount_context_weakref_is_valid(const RefcountContext *ctx,
|
||||
RefcountWeakref *wr);
|
||||
|
||||
void *refcount_context_ref_weakref(const RefcountContext *ctx,
|
||||
const RefcountWeakref *wr);
|
||||
RefcountWeakref *wr);
|
||||
|
||||
/**
|
||||
* Convenience function that calls #refcount_context_ref_weakref followed by
|
||||
@ -238,9 +222,6 @@ static inline void *refcount_context_strengthen(const RefcountContext *ctx,
|
||||
static inline RefcountWeakref *refcount_context_weaken(RefcountContext *ctx,
|
||||
void *obj) {
|
||||
RefcountWeakref *wr = refcount_context_make_weakref(ctx, obj);
|
||||
if (!wr) {
|
||||
return NULL;
|
||||
}
|
||||
refcount_context_unref(ctx, obj);
|
||||
return wr;
|
||||
}
|
||||
|
Reference in New Issue
Block a user