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