mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
miniobject: add steal_qdata
Rework the qdata code a little
This commit is contained in:
parent
03ac16c1d8
commit
d3f5dd0707
3 changed files with 128 additions and 87 deletions
|
@ -71,14 +71,16 @@ static GQuark weak_ref_quark;
|
|||
typedef struct
|
||||
{
|
||||
GQuark quark;
|
||||
GstMiniObjectWeakNotify notify;
|
||||
GstMiniObjectNotify notify;
|
||||
gpointer data;
|
||||
GDestroyNotify destroy;
|
||||
} GstQData;
|
||||
|
||||
#define QDATA(o,i) ((GstQData *)(o)->qdata)[(i)]
|
||||
#define QDATA_QUARK(o,i) (QDATA(o,i).quark)
|
||||
#define QDATA_NOTIFY(o,i) (QDATA(o,i).notify)
|
||||
#define QDATA_DATA(o,i) (QDATA(o,i).data)
|
||||
#define QDATA(o,i) ((GstQData *)(o)->qdata)[(i)]
|
||||
#define QDATA_QUARK(o,i) (QDATA(o,i).quark)
|
||||
#define QDATA_NOTIFY(o,i) (QDATA(o,i).notify)
|
||||
#define QDATA_DATA(o,i) (QDATA(o,i).data)
|
||||
#define QDATA_DESTROY(o,i) (QDATA(o,i).destroy)
|
||||
|
||||
void
|
||||
_priv_gst_mini_object_initialize (void)
|
||||
|
@ -238,14 +240,62 @@ gst_mini_object_ref (GstMiniObject * mini_object)
|
|||
return mini_object;
|
||||
}
|
||||
|
||||
static void
|
||||
qdata_notify (GstMiniObject * obj)
|
||||
static gint
|
||||
find_notify (GstMiniObject * object, GQuark quark, gboolean match_notify,
|
||||
GstMiniObjectNotify notify, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < obj->n_qdata; i++)
|
||||
QDATA_NOTIFY (obj, i) (QDATA_DATA (obj, i), obj);
|
||||
g_free (obj->qdata);
|
||||
for (i = 0; i < object->n_qdata; i++) {
|
||||
if (QDATA_QUARK (object, i) == quark) {
|
||||
/* check if we need to match the callback too */
|
||||
if (!match_notify || (QDATA_NOTIFY (object, i) == notify &&
|
||||
QDATA_DATA (object, i) == data))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_notify (GstMiniObject * object, gint index)
|
||||
{
|
||||
/* remove item */
|
||||
if (--object->n_qdata == 0) {
|
||||
/* we don't shrink but free when everything is gone */
|
||||
g_free (object->qdata);
|
||||
object->qdata = NULL;
|
||||
} else if (index != object->n_qdata)
|
||||
QDATA (object, index) = QDATA (object, object->n_qdata);
|
||||
}
|
||||
|
||||
static void
|
||||
set_notify (GstMiniObject * object, gint index, GQuark quark,
|
||||
GstMiniObjectNotify notify, gpointer data, GDestroyNotify destroy)
|
||||
{
|
||||
if (index == -1) {
|
||||
/* add item */
|
||||
index = object->n_qdata++;
|
||||
object->qdata =
|
||||
g_realloc (object->qdata, sizeof (GstQData) * object->n_qdata);
|
||||
}
|
||||
QDATA_QUARK (object, index) = quark;
|
||||
QDATA_NOTIFY (object, index) = notify;
|
||||
QDATA_DATA (object, index) = data;
|
||||
QDATA_DESTROY (object, index) = destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
call_finalize_notify (GstMiniObject * obj)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < obj->n_qdata; i++) {
|
||||
if (QDATA_QUARK (obj, i) == weak_ref_quark)
|
||||
QDATA_NOTIFY (obj, i) (QDATA_DATA (obj, i), obj);
|
||||
if (QDATA_DESTROY (obj, i))
|
||||
QDATA_DESTROY (obj, i) (QDATA_DATA (obj, i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,10 +328,10 @@ gst_mini_object_unref (GstMiniObject * mini_object)
|
|||
/* if the subclass recycled the object (and returned FALSE) we don't
|
||||
* want to free the instance anymore */
|
||||
if (G_LIKELY (do_free)) {
|
||||
/* The weak reference stack is freed in the notification function */
|
||||
if (mini_object->n_qdata)
|
||||
qdata_notify (mini_object);
|
||||
|
||||
if (mini_object->n_qdata) {
|
||||
call_finalize_notify (mini_object);
|
||||
g_free (mini_object->qdata);
|
||||
}
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
|
||||
#endif
|
||||
|
@ -423,21 +473,14 @@ gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata)
|
|||
*/
|
||||
void
|
||||
gst_mini_object_weak_ref (GstMiniObject * object,
|
||||
GstMiniObjectWeakNotify notify, gpointer data)
|
||||
GstMiniObjectNotify notify, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (notify != NULL);
|
||||
g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
|
||||
|
||||
G_LOCK (qdata_mutex);
|
||||
i = object->n_qdata++;
|
||||
object->qdata =
|
||||
g_realloc (object->qdata, sizeof (GstQData) * object->n_qdata);
|
||||
QDATA_QUARK (object, i) = weak_ref_quark;
|
||||
QDATA_NOTIFY (object, i) = notify;
|
||||
QDATA_DATA (object, i) = data;
|
||||
set_notify (object, -1, weak_ref_quark, notify, data, NULL);
|
||||
G_UNLOCK (qdata_mutex);
|
||||
}
|
||||
|
||||
|
@ -447,38 +490,26 @@ gst_mini_object_weak_ref (GstMiniObject * object,
|
|||
* @notify: callback to search for
|
||||
* @data: data to search for
|
||||
*
|
||||
* Removes a weak reference callback to a mini object.
|
||||
* Removes a weak reference callback from a mini object.
|
||||
*
|
||||
* Since: 0.10.35
|
||||
*/
|
||||
void
|
||||
gst_mini_object_weak_unref (GstMiniObject * object,
|
||||
GstMiniObjectWeakNotify notify, gpointer data)
|
||||
GstMiniObjectNotify notify, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
gboolean found_one = FALSE;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (notify != NULL);
|
||||
|
||||
G_LOCK (qdata_mutex);
|
||||
for (i = 0; i < object->n_qdata; i++) {
|
||||
if (QDATA_QUARK (object, i) == weak_ref_quark &&
|
||||
QDATA_NOTIFY (object, i) == notify && QDATA_DATA (object, i) == data) {
|
||||
found_one = TRUE;
|
||||
if (--object->n_qdata == 0) {
|
||||
/* we don't shrink but free when everything is gone */
|
||||
g_free (object->qdata);
|
||||
object->qdata = NULL;
|
||||
} else if (i != object->n_qdata)
|
||||
QDATA (object, i) = QDATA (object, object->n_qdata);
|
||||
break;
|
||||
}
|
||||
if ((i = find_notify (object, weak_ref_quark, TRUE, notify, data)) != -1) {
|
||||
remove_notify (object, i);
|
||||
} else {
|
||||
g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
|
||||
}
|
||||
G_UNLOCK (qdata_mutex);
|
||||
|
||||
if (!found_one)
|
||||
g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,7 +537,7 @@ void
|
|||
gst_mini_object_set_qdata (GstMiniObject * object, GQuark quark,
|
||||
gpointer data, GDestroyNotify destroy)
|
||||
{
|
||||
guint i;
|
||||
gint i;
|
||||
gpointer old_data = NULL;
|
||||
GDestroyNotify old_notify = NULL;
|
||||
|
||||
|
@ -514,32 +545,16 @@ gst_mini_object_set_qdata (GstMiniObject * object, GQuark quark,
|
|||
g_return_if_fail (quark > 0);
|
||||
|
||||
G_LOCK (qdata_mutex);
|
||||
for (i = 0; i < object->n_qdata; i++) {
|
||||
if (QDATA_QUARK (object, i) == quark) {
|
||||
old_data = QDATA_DATA (object, i);
|
||||
old_notify = (GDestroyNotify) QDATA_NOTIFY (object, i);
|
||||
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) {
|
||||
|
||||
if (data == NULL) {
|
||||
/* remove item */
|
||||
if (--object->n_qdata == 0) {
|
||||
/* we don't shrink but free when everything is gone */
|
||||
g_free (object->qdata);
|
||||
object->qdata = NULL;
|
||||
} else if (i != object->n_qdata)
|
||||
QDATA (object, i) = QDATA (object, object->n_qdata);
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_data = QDATA_DATA (object, i);
|
||||
old_notify = QDATA_DESTROY (object, i);
|
||||
|
||||
if (data == NULL)
|
||||
remove_notify (object, i);
|
||||
}
|
||||
if (!old_data) {
|
||||
/* add item */
|
||||
i = object->n_qdata++;
|
||||
object->qdata =
|
||||
g_realloc (object->qdata, sizeof (GstQData) * object->n_qdata);
|
||||
}
|
||||
QDATA_QUARK (object, i) = quark;
|
||||
QDATA_DATA (object, i) = data;
|
||||
QDATA_NOTIFY (object, i) = (GstMiniObjectWeakNotify) destroy;
|
||||
if (data != NULL)
|
||||
set_notify (object, i, quark, NULL, data, destroy);
|
||||
G_UNLOCK (qdata_mutex);
|
||||
|
||||
if (old_notify)
|
||||
|
@ -560,17 +575,47 @@ gpointer
|
|||
gst_mini_object_get_qdata (GstMiniObject * object, GQuark quark)
|
||||
{
|
||||
guint i;
|
||||
gpointer result = NULL;
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (object != NULL, NULL);
|
||||
g_return_val_if_fail (quark > 0, NULL);
|
||||
|
||||
G_LOCK (qdata_mutex);
|
||||
for (i = 0; i < object->n_qdata; i++) {
|
||||
if (QDATA_QUARK (object, i) == quark) {
|
||||
result = QDATA_DATA (object, i);
|
||||
break;
|
||||
}
|
||||
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1)
|
||||
result = QDATA_DATA (object, i);
|
||||
else
|
||||
result = NULL;
|
||||
G_UNLOCK (qdata_mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mini_object_steal_qdata:
|
||||
* @object: The GstMiniObject to get a stored user data pointer from
|
||||
* @quark: A #GQuark, naming the user data pointer
|
||||
*
|
||||
* This function gets back user data pointers stored via gst_mini_object_set_qdata()
|
||||
* and removes the data from @object without invoking its destroy() function (if
|
||||
* any was set).
|
||||
*
|
||||
* Returns: (transfer full): The user data pointer set, or %NULL
|
||||
*/
|
||||
gpointer
|
||||
gst_mini_object_steal_qdata (GstMiniObject * object, GQuark quark)
|
||||
{
|
||||
guint i;
|
||||
gpointer result;
|
||||
|
||||
g_return_val_if_fail (object != NULL, NULL);
|
||||
g_return_val_if_fail (quark > 0, NULL);
|
||||
|
||||
G_LOCK (qdata_mutex);
|
||||
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) {
|
||||
result = QDATA_DATA (object, i);
|
||||
remove_notify (object, i);
|
||||
} else {
|
||||
result = NULL;
|
||||
}
|
||||
G_UNLOCK (qdata_mutex);
|
||||
|
||||
|
|
|
@ -68,20 +68,14 @@ typedef gboolean (*GstMiniObjectDisposeFunction) (GstMiniObject *obj);
|
|||
typedef void (*GstMiniObjectFreeFunction) (GstMiniObject *obj);
|
||||
|
||||
/**
|
||||
* GstMiniObjectWeakNotify:
|
||||
* @user_data: data that was provided when the weak reference was established
|
||||
* @where_the_mini_object_was: the mini object being finalized
|
||||
* GstMiniObjectNotify:
|
||||
* @user_data: data that was provided when the notify was added
|
||||
* @obj: the mini object
|
||||
*
|
||||
* A #GstMiniObjectWeakNotify function can be added to a mini object as a
|
||||
* callback that gets triggered when the mini object is finalized. Since the
|
||||
* mini object is already being finalized when the #GstMiniObjectWeakNotify is
|
||||
* called, there's not much you could do with the object, apart from e.g. using
|
||||
* its adress as hash-index or the like.
|
||||
*
|
||||
* Since: 0.10.35
|
||||
* A #GstMiniObjectNotify function can be added to a mini object as a
|
||||
* callback that gets triggered with gst_mini_object_notify().
|
||||
*/
|
||||
typedef void (*GstMiniObjectWeakNotify) (gpointer user_data,
|
||||
GstMiniObject * where_the_mini_object_was);
|
||||
typedef void (*GstMiniObjectNotify) (gpointer user_data, GstMiniObject * obj);
|
||||
|
||||
/**
|
||||
* GST_MINI_OBJECT_TYPE:
|
||||
|
@ -195,15 +189,16 @@ GstMiniObject * gst_mini_object_ref (GstMiniObject *mini_object);
|
|||
void gst_mini_object_unref (GstMiniObject *mini_object);
|
||||
|
||||
void gst_mini_object_weak_ref (GstMiniObject *object,
|
||||
GstMiniObjectWeakNotify notify,
|
||||
GstMiniObjectNotify notify,
|
||||
gpointer data);
|
||||
void gst_mini_object_weak_unref (GstMiniObject *object,
|
||||
GstMiniObjectWeakNotify notify,
|
||||
GstMiniObjectNotify notify,
|
||||
gpointer data);
|
||||
|
||||
void gst_mini_object_set_qdata (GstMiniObject *object, GQuark quark,
|
||||
gpointer data, GDestroyNotify destroy);
|
||||
gpointer gst_mini_object_get_qdata (GstMiniObject *object, GQuark quark);
|
||||
gpointer gst_mini_object_steal_qdata (GstMiniObject *object, GQuark quark);
|
||||
|
||||
|
||||
gboolean gst_mini_object_replace (GstMiniObject **olddata, GstMiniObject *newdata);
|
||||
|
|
|
@ -603,6 +603,7 @@ EXPORTS
|
|||
gst_mini_object_replace
|
||||
gst_mini_object_set_qdata
|
||||
gst_mini_object_steal
|
||||
gst_mini_object_steal_qdata
|
||||
gst_mini_object_take
|
||||
gst_mini_object_unref
|
||||
gst_mini_object_weak_ref
|
||||
|
|
Loading…
Reference in a new issue