mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 03:02:10 +01:00
Add atomically reference counted memory
Similar to g_ref_*, we have g_atomic_ref_*, which will ensure that all reference counting operations are performed atomically. Not every data structure needs atomic reference counting; for instance, most of the GTK+ data structures operate under the assumption that only one thread can access windowing system data. Since atomic operations are not cheap, forcing them on every data structure can negatively affect performance. The underlying reference counting mechanism for g_atomic_ref_* is the same as for g_ref_*, but instead of adding a "make this atomic" boolean flag to the g_ref_* API we prefer being explicit, and add the "atomic" qualifier directly into the API, to avoid misunderstandings.
This commit is contained in:
parent
b49fd4c730
commit
43ed42e4d5
@ -326,3 +326,60 @@ g_ref_release (gpointer ref)
|
|||||||
if (g_ref_counter_release (&real_ref->ref_count))
|
if (g_ref_counter_release (&real_ref->ref_count))
|
||||||
g_ref_free (ref);
|
g_ref_free (ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
g_atomic_ref_alloc (gsize size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
|
||||||
|
return g_ref_alloc_internal (size, FALSE, TRUE, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
g_atomic_ref_alloc0 (gsize size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
|
||||||
|
return g_ref_alloc_internal (size, TRUE, TRUE, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
g_atomic_ref_dup (gconstpointer data,
|
||||||
|
gsize size,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
gpointer res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
|
||||||
|
res = g_ref_alloc_internal (size, FALSE, TRUE, notify);
|
||||||
|
|
||||||
|
memcpy (res, data, size);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
g_atomic_ref_acquire (gpointer ref)
|
||||||
|
{
|
||||||
|
GRef *real_ref = G_REF (ref);
|
||||||
|
|
||||||
|
g_return_val_if_fail (ref != NULL, NULL);
|
||||||
|
|
||||||
|
g_ref_counter_acquire (&real_ref->ref_count);
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
g_atomic_ref_release (gpointer ref)
|
||||||
|
{
|
||||||
|
GRef *real_ref = G_REF (ref);
|
||||||
|
|
||||||
|
g_return_if_fail (ref != NULL);
|
||||||
|
|
||||||
|
if (g_ref_counter_release (&real_ref->ref_count))
|
||||||
|
g_ref_free (ref);
|
||||||
|
}
|
||||||
|
@ -59,6 +59,27 @@ gpointer g_ref_acquire (gpointer ref);
|
|||||||
GLIB_AVAILABLE_IN_2_52
|
GLIB_AVAILABLE_IN_2_52
|
||||||
void g_ref_release (gpointer ref);
|
void g_ref_release (gpointer ref);
|
||||||
|
|
||||||
|
#define g_atomic_ref_new(Type,Notify) \
|
||||||
|
(Type *) g_atomic_ref_alloc (sizeof (Type), Notify)
|
||||||
|
|
||||||
|
#define g_atomic_ref_new0(Type,Notify) \
|
||||||
|
(Type *) g_atomic_ref_alloc0 (sizeof (Type), Notify)
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_52
|
||||||
|
gpointer g_atomic_ref_alloc (gsize size,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
GLIB_AVAILABLE_IN_2_52
|
||||||
|
gpointer g_atomic_ref_alloc0 (gsize size,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
GLIB_AVAILABLE_IN_2_52
|
||||||
|
gpointer g_atomic_ref_dup (gconstpointer data,
|
||||||
|
gsize size,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
GLIB_AVAILABLE_IN_2_52
|
||||||
|
gpointer g_atomic_ref_acquire (gpointer ref);
|
||||||
|
GLIB_AVAILABLE_IN_2_52
|
||||||
|
void g_atomic_ref_release (gpointer ref);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_REF_COUNT_H__ */
|
#endif /* __G_REF_COUNT_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user