5 #ifndef __MONO_UTILS_REFCOUNT_H__
6 #define __MONO_UTILS_REFCOUNT_H__
14 * Mechanism for ref-counting which tries to be as user-friendly as possible. Instead of being a wrapper around
15 * user-provided data, it is embedded into the user data.
17 * This introduces some constraints on the MonoRefCount field:
18 * - it needs to be called "ref"
19 * - it cannot be a pointer
24 void (*destructor
) (gpointer data
);
27 #define mono_refcount_init(v,destructor) do { mono_refcount_initialize (&(v)->ref, (destructor)); } while (0)
28 #define mono_refcount_inc(v) (mono_refcount_increment (&(v)->ref),(v))
29 #define mono_refcount_tryinc(v) (mono_refcount_tryincrement (&(v)->ref))
30 #define mono_refcount_dec(v) (mono_refcount_decrement (&(v)->ref))
33 mono_refcount_initialize (MonoRefCount
*refcount
, void (*destructor
) (gpointer data
))
36 refcount
->destructor
= destructor
;
39 static inline gboolean
40 mono_refcount_tryincrement (MonoRefCount
*refcount
)
42 guint32 oldref
, newref
;
47 oldref
= refcount
->ref
;
52 } while (mono_atomic_cas_i32 ((gint32
*) &refcount
->ref
, (gint32
)newref
, (gint32
)oldref
) != (gint32
)oldref
);
58 mono_refcount_increment (MonoRefCount
*refcount
)
60 if (!mono_refcount_tryincrement (refcount
))
61 g_error ("%s: cannot increment a ref with value 0", __func__
);
65 mono_refcount_decrement (MonoRefCount
*refcount
)
67 guint32 oldref
, newref
;
72 oldref
= refcount
->ref
;
74 g_error ("%s: cannot decrement a ref with value 0", __func__
);
77 } while (mono_atomic_cas_i32 ((gint32
*) &refcount
->ref
, (gint32
)newref
, (gint32
)oldref
) != (gint32
)oldref
);
79 if (newref
== 0 && refcount
->destructor
)
80 refcount
->destructor ((gpointer
) refcount
);
85 #endif /* __MONO_UTILS_REFCOUNT_H__ */