[StShadow] Add reference counting

If a shadow property is inherited from a parent, multiple StThemeNodes
share a common StShadow. It would be possible to use st_shadow_copy()
for this purpose, but proper reference counting is nicer.

https://bugzilla.gnome.org/show_bug.cgi?id=624384
This commit is contained in:
Florian Müllner 2010-09-01 11:16:31 +02:00
parent c3b88d4113
commit e942444630
3 changed files with 27 additions and 21 deletions

View File

@ -36,45 +36,50 @@ st_shadow_new (ClutterColor *color,
shadow = g_slice_new (StShadow); shadow = g_slice_new (StShadow);
shadow->color = *color; shadow->color = *color;
shadow->xoffset = xoffset; shadow->xoffset = xoffset;
shadow->yoffset = yoffset; shadow->yoffset = yoffset;
shadow->blur = blur; shadow->blur = blur;
shadow->spread = spread; shadow->spread = spread;
shadow->ref_count = 1;
return shadow; return shadow;
} }
/** /**
* st_shadow_copy: * st_shadow_ref:
* @shadow: a #StShadow * @shadow: a #StShadow
* *
* Makes a copy of @shadow. * Atomically increments the reference count of @shadow by one.
* *
* Returns: an allocated copy of @shadow - the result must be freed with * Returns: the passed in #StShadow.
* st_shadow_free() when done
*/ */
StShadow * StShadow *
st_shadow_copy (const StShadow *shadow) st_shadow_ref (StShadow *shadow)
{ {
g_return_val_if_fail (shadow != NULL, NULL); g_return_val_if_fail (shadow != NULL, NULL);
g_return_val_if_fail (shadow->ref_count > 0, shadow);
return g_slice_dup (StShadow, shadow); g_atomic_int_add (&shadow->ref_count, 1);
return shadow;
} }
/** /**
* st_shadow_free: * st_shadow_unref:
* @shadow: a #StShadow * @shadow: a #StShadow
* *
* Frees the shadow structure created with st_shadow_new() or * Atomically decrements the reference count of @shadow by one.
* st_shadow_copy() * If the reference count drops to 0, all memory allocated by the
* #StShadow is released.
*/ */
void void
st_shadow_free (StShadow *shadow) st_shadow_unref (StShadow *shadow)
{ {
g_return_if_fail (shadow != NULL); g_return_if_fail (shadow != NULL);
g_return_if_fail (shadow->ref_count > 0);
g_slice_free (StShadow, shadow); if (g_atomic_int_exchange_and_add (&shadow->ref_count, -1) - 1 == 0)
g_slice_free (StShadow, shadow);
} }
/** /**
@ -144,8 +149,8 @@ st_shadow_get_type (void)
if (G_UNLIKELY (_st_shadow_type == 0)) if (G_UNLIKELY (_st_shadow_type == 0))
_st_shadow_type = _st_shadow_type =
g_boxed_type_register_static ("StShadow", g_boxed_type_register_static ("StShadow",
(GBoxedCopyFunc) st_shadow_copy, (GBoxedCopyFunc) st_shadow_ref,
(GBoxedFreeFunc) st_shadow_free); (GBoxedFreeFunc) st_shadow_unref);
return _st_shadow_type; return _st_shadow_type;
} }

View File

@ -29,6 +29,7 @@ struct _StShadow {
gdouble yoffset; gdouble yoffset;
gdouble blur; gdouble blur;
gdouble spread; gdouble spread;
volatile int ref_count;
}; };
GType st_shadow_get_type (void) G_GNUC_CONST; GType st_shadow_get_type (void) G_GNUC_CONST;
@ -38,8 +39,8 @@ StShadow *st_shadow_new (ClutterColor *color,
gdouble yoffset, gdouble yoffset,
gdouble blur, gdouble blur,
gdouble spread); gdouble spread);
StShadow *st_shadow_copy (const StShadow *shadow); StShadow *st_shadow_ref (StShadow *shadow);
void st_shadow_free (StShadow *shadow); void st_shadow_unref (StShadow *shadow);
gboolean st_shadow_equal (StShadow *shadow, gboolean st_shadow_equal (StShadow *shadow,
StShadow *other); StShadow *other);

View File

@ -99,7 +99,7 @@ st_theme_node_finalize (GObject *object)
if (node->shadow) if (node->shadow)
{ {
st_shadow_free (node->shadow); st_shadow_unref (node->shadow);
node->shadow = NULL; node->shadow = NULL;
} }