Fork me on GitHub
refcount.h
Go to the documentation of this file.
1 
57 #ifndef JANUS_REFCOUNT_H
58 #define JANUS_REFCOUNT_H
59 
60 #include <glib.h>
61 #include "mutex.h"
62 
63 //~ #define REFCOUNT_DEBUG
64 
65 extern int refcount_debug;
66 
72 #define janus_refcount_containerof(refptr, type, member) \
73  ((type *)((char *)(refptr) - offsetof(type, member)))
74 
75 
80  gint count;
82  void (*free)(const janus_refcount *);
83 };
84 
85 
86 #ifdef REFCOUNT_DEBUG
87 /* Reference counters debugging */
88 extern GHashTable *counters;
89 extern janus_mutex counters_mutex;
90 #define janus_refcount_track(refp) { \
91  janus_mutex_lock(&counters_mutex); \
92  if(counters == NULL) \
93  counters = g_hash_table_new(NULL, NULL); \
94  g_hash_table_insert(counters, refp, refp); \
95  janus_mutex_unlock(&counters_mutex); \
96 }
97 #define janus_refcount_untrack(refp) { \
98  janus_mutex_lock(&counters_mutex); \
99  g_hash_table_remove(counters, refp); \
100  janus_mutex_unlock(&counters_mutex); \
101 }
102 #endif
103 
104 
111 #define janus_refcount_init(refp, free_fn) { \
112  if(!refcount_debug) { \
113  janus_refcount_init_nodebug(refp, free_fn); \
114  } else { \
115  janus_refcount_init_debug(refp, free_fn); \
116  } \
117 }
118 
124 #ifdef REFCOUNT_DEBUG
125 #define janus_refcount_init_nodebug(refp, free_fn) { \
126  (refp)->count = 1; \
127  (refp)->free = free_fn; \
128  janus_refcount_track((refp)); \
129 }
130 #else
131 #define janus_refcount_init_nodebug(refp, free_fn) { \
132  (refp)->count = 1; \
133  (refp)->free = free_fn; \
134 }
135 #endif
136 
142 #ifdef REFCOUNT_DEBUG
143 #define janus_refcount_init_debug(refp, free_fn) { \
144  (refp)->count = 1; \
145  JANUS_PRINT("[%s:%s:%d:init] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count); \
146  (refp)->free = free_fn; \
147  janus_refcount_track((refp)); \
148 }
149 #else
150 #define janus_refcount_init_debug(refp, free_fn) { \
151  (refp)->count = 1; \
152  JANUS_PRINT("[%s:%s:%d:init] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count); \
153  (refp)->free = free_fn; \
154 }
155 #endif
156 
159 #define janus_refcount_increase(refp) { \
160  if(!refcount_debug) { \
161  janus_refcount_increase_nodebug(refp); \
162  } else { \
163  janus_refcount_increase_debug(refp); \
164  } \
165 }
166 
168 #define janus_refcount_increase_nodebug(refp) { \
169  g_atomic_int_inc((gint *)&(refp)->count); \
170 }
171 
173 #define janus_refcount_increase_debug(refp) { \
174  JANUS_PRINT("[%s:%s:%d:increase] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count+1); \
175  g_atomic_int_inc((gint *)&(refp)->count); \
176 }
177 
181 #define janus_refcount_decrease(refp) { \
182  if(!refcount_debug) { \
183  janus_refcount_decrease_nodebug(refp); \
184  } else { \
185  janus_refcount_decrease_debug(refp); \
186  } \
187 }
188 
191 #ifdef REFCOUNT_DEBUG
192 #define janus_refcount_decrease_debug(refp) { \
193  JANUS_PRINT("[%s:%s:%d:decrease] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count-1); \
194  if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
195  (refp)->free(refp); \
196  janus_refcount_untrack((refp)); \
197  } \
198 }
199 #else
200 #define janus_refcount_decrease_debug(refp) { \
201  JANUS_PRINT("[%s:%s:%d:decrease] %p (%d)\n", __FILE__, __FUNCTION__, __LINE__, refp, (refp)->count-1); \
202  if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
203  (refp)->free(refp); \
204  } \
205 }
206 #endif
207 
210 #ifdef REFCOUNT_DEBUG
211 #define janus_refcount_decrease_nodebug(refp) { \
212  if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
213  (refp)->free(refp); \
214  janus_refcount_untrack((refp)); \
215  } \
216 }
217 #else
218 #define janus_refcount_decrease_nodebug(refp) { \
219  if(g_atomic_int_dec_and_test((gint *)&(refp)->count)) { \
220  (refp)->free(refp); \
221  } \
222 }
223 #endif
224 
225 #endif
GMutex janus_mutex
Janus mutex implementation.
Definition: mutex.h:61
Definition: refcount.h:78
int refcount_debug
Definition: janus.c:437
Semaphors, Mutexes and Conditions.
void(* free)(const janus_refcount *)
Pointer to the function that will be used to free the object.
Definition: refcount.h:82
gint count
The reference counter itself.
Definition: refcount.h:80