docs: improve API docs
[platform/upstream/gstreamer.git] / gst / gstminiobject.c
1 /* GStreamer
2  * Copyright (C) 2005 David Schleef <ds@schleef.org>
3  *
4  * gstminiobject.h: Header for GstMiniObject
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 /**
22  * SECTION:gstminiobject
23  * @short_description: Lightweight base class for the GStreamer object hierarchy
24  *
25  * #GstMiniObject is a simple structure that can be used to implement refcounted
26  * types.
27  *
28  * Subclasses will include #GstMiniObject as the first member in their structure
29  * and then call gst_mini_object_init() to initialize the #GstMiniObject fields.
30  *
31  * gst_mini_object_ref() and gst_mini_object_unref() increment and decrement the
32  * refcount respectively. When the refcount of a mini-object reaches 0, the
33  * dispose function is called first and when this returns %TRUE, the free
34  * function of the miniobject is called.
35  *
36  * A copy can be made with gst_mini_object_copy().
37  *
38  * gst_mini_object_is_writable() will return %TRUE when the refcount of the
39  * object is exactly 1, meaning the current caller has the only reference to the
40  * object. gst_mini_object_make_writable() will return a writable version of the
41  * object, which might be a new copy when the refcount was not 1.
42  *
43  * Opaque data can be associated with a #GstMiniObject with
44  * gst_mini_object_set_qdata() and gst_mini_object_get_qdata(). The data is
45  * meant to be specific to the particular object and is not automatically copied
46  * with gst_mini_object_copy() or similar methods.
47  *
48  * A weak reference can be added and remove with gst_mini_object_weak_ref()
49  * and gst_mini_object_weak_unref() respectively.
50  *
51  * Last reviewed on 2012-06-15 (0.11.93)
52  */
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #include "gst/gst_private.h"
58 #include "gst/gstminiobject.h"
59 #include "gst/gstinfo.h"
60 #include <gobject/gvaluecollector.h>
61
62 #ifndef GST_DISABLE_TRACE
63 #include "gsttrace.h"
64 static GstAllocTrace *_gst_mini_object_trace;
65 #endif
66
67 /* Mutex used for weak referencing */
68 G_LOCK_DEFINE_STATIC (qdata_mutex);
69 static GQuark weak_ref_quark;
70
71 void
72 _priv_gst_mini_object_initialize (void)
73 {
74   weak_ref_quark = g_quark_from_static_string ("GstMiniObjectWeakRefQuark");
75
76 #ifndef GST_DISABLE_TRACE
77   _gst_mini_object_trace = _gst_alloc_trace_register ("GstMiniObject", 0);
78 #endif
79 }
80
81 /**
82  * gst_mini_object_init:
83  * @mini_object: a #GstMiniObject 
84  * @type: the #GType of the mini-object to create
85  *
86  * Initializes a mini-object with the desired type and size.
87  *
88  * MT safe
89  *
90  * Returns: (transfer full): the new mini-object.
91  */
92 void
93 gst_mini_object_init (GstMiniObject * mini_object, GType type)
94 {
95   mini_object->type = type;
96   mini_object->refcount = 1;
97   mini_object->flags = 0;
98   mini_object->n_qdata = 0;
99   mini_object->qdata = NULL;
100
101 #ifndef GST_DISABLE_TRACE
102   _gst_alloc_trace_new (_gst_mini_object_trace, mini_object);
103 #endif
104 }
105
106 /**
107  * gst_mini_object_copy:
108  * @mini_object: the mini-object to copy
109  *
110  * Creates a copy of the mini-object.
111  *
112  * MT safe
113  *
114  * Returns: (transfer full): the new mini-object.
115  */
116 GstMiniObject *
117 gst_mini_object_copy (const GstMiniObject * mini_object)
118 {
119   GstMiniObject *copy;
120
121   g_return_val_if_fail (mini_object != NULL, NULL);
122
123   if (mini_object->copy)
124     copy = mini_object->copy (mini_object);
125   else
126     copy = NULL;
127
128   return copy;
129 }
130
131 /**
132  * gst_mini_object_is_writable:
133  * @mini_object: the mini-object to check
134  *
135  * Checks if a mini-object is writable.  A mini-object is writable
136  * if the reference count is one. Modification of a mini-object should
137  * only be done after verifying that it is writable.
138  *
139  * MT safe
140  *
141  * Returns: TRUE if the object is writable.
142  */
143 gboolean
144 gst_mini_object_is_writable (const GstMiniObject * mini_object)
145 {
146   g_return_val_if_fail (mini_object != NULL, FALSE);
147
148   return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
149 }
150
151 /**
152  * gst_mini_object_make_writable:
153  * @mini_object: (transfer full): the mini-object to make writable
154  *
155  * Checks if a mini-object is writable.  If not, a writable copy is made and
156  * returned.  This gives away the reference to the original mini object,
157  * and returns a reference to the new object.
158  *
159  * MT safe
160  *
161  * Returns: (transfer full): a mini-object (possibly the same pointer) that
162  *     is writable.
163  */
164 GstMiniObject *
165 gst_mini_object_make_writable (GstMiniObject * mini_object)
166 {
167   GstMiniObject *ret;
168
169   g_return_val_if_fail (mini_object != NULL, NULL);
170
171   if (gst_mini_object_is_writable (mini_object)) {
172     ret = mini_object;
173   } else {
174     ret = gst_mini_object_copy (mini_object);
175     GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy %s miniobject %p -> %p",
176         g_type_name (GST_MINI_OBJECT_TYPE (mini_object)), mini_object, ret);
177     gst_mini_object_unref (mini_object);
178   }
179
180   return ret;
181 }
182
183 /**
184  * gst_mini_object_ref:
185  * @mini_object: the mini-object
186  *
187  * Increase the reference count of the mini-object.
188  *
189  * Note that the refcount affects the writeability
190  * of @mini-object, see gst_mini_object_is_writable(). It is
191  * important to note that keeping additional references to
192  * GstMiniObject instances can potentially increase the number
193  * of memcpy operations in a pipeline, especially if the miniobject
194  * is a #GstBuffer.
195  *
196  * Returns: (transfer full): the mini-object.
197  */
198 GstMiniObject *
199 gst_mini_object_ref (GstMiniObject * mini_object)
200 {
201   g_return_val_if_fail (mini_object != NULL, NULL);
202   /* we can't assert that the refcount > 0 since the _free functions
203    * increments the refcount from 0 to 1 again to allow resurecting
204    * the object
205    g_return_val_if_fail (mini_object->refcount > 0, NULL);
206    */
207
208   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p ref %d->%d", mini_object,
209       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
210       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) + 1);
211
212   g_atomic_int_inc (&mini_object->refcount);
213
214   return mini_object;
215 }
216
217 static void
218 qdata_notify (GstMiniObject * obj)
219 {
220   guint i;
221
222   for (i = 0; i < obj->n_qdata; i++)
223     obj->qdata[i].notify (obj->qdata[i].data, obj);
224   g_free (obj->qdata);
225 }
226
227 /**
228  * gst_mini_object_unref:
229  * @mini_object: the mini-object
230  *
231  * Decreases the reference count of the mini-object, possibly freeing
232  * the mini-object.
233  */
234 void
235 gst_mini_object_unref (GstMiniObject * mini_object)
236 {
237   g_return_if_fail (mini_object != NULL);
238
239   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p unref %d->%d",
240       mini_object,
241       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
242       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);
243
244   g_return_if_fail (mini_object->refcount > 0);
245
246   if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
247     gboolean do_free;
248
249     if (mini_object->dispose)
250       do_free = mini_object->dispose (mini_object);
251     else
252       do_free = TRUE;
253
254     /* if the subclass recycled the object (and returned FALSE) we don't
255      * want to free the instance anymore */
256     if (G_LIKELY (do_free)) {
257       /* The weak reference stack is freed in the notification function */
258       if (mini_object->n_qdata)
259         qdata_notify (mini_object);
260
261 #ifndef GST_DISABLE_TRACE
262       _gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
263 #endif
264       if (mini_object->free)
265         mini_object->free (mini_object);
266     }
267   }
268 }
269
270 /**
271  * gst_mini_object_replace:
272  * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
273  *     be replaced
274  * @newdata: pointer to new mini-object
275  *
276  * Atomically modifies a pointer to point to a new mini-object.
277  * The reference count of @olddata is decreased and the reference count of
278  * @newdata is increased.
279  *
280  * Either @newdata and the value pointed to by @olddata may be NULL.
281  *
282  * Returns: TRUE if @newdata was different from @olddata
283  */
284 gboolean
285 gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
286 {
287   GstMiniObject *olddata_val;
288
289   g_return_val_if_fail (olddata != NULL, FALSE);
290
291   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p (%d) with %p (%d)",
292       *olddata, *olddata ? (*olddata)->refcount : 0,
293       newdata, newdata ? newdata->refcount : 0);
294
295   olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
296
297   if (G_UNLIKELY (olddata_val == newdata))
298     return FALSE;
299
300   if (newdata)
301     gst_mini_object_ref (newdata);
302
303   while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
304               olddata, olddata_val, newdata))) {
305     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
306     if (G_UNLIKELY (olddata_val == newdata))
307       break;
308   }
309
310   if (olddata_val)
311     gst_mini_object_unref (olddata_val);
312
313   return olddata_val != newdata;
314 }
315
316 /**
317  * gst_mini_object_steal:
318  * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
319  *     be stolen
320  *
321  * Replace the current #GstMiniObject pointer to by @olddata with NULL and
322  * return the old value.
323  *
324  * Returns: the #GstMiniObject at @oldata
325  */
326 GstMiniObject *
327 gst_mini_object_steal (GstMiniObject ** olddata)
328 {
329   GstMiniObject *olddata_val;
330
331   g_return_val_if_fail (olddata != NULL, NULL);
332
333   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "steal %p (%d)",
334       *olddata, *olddata ? (*olddata)->refcount : 0);
335
336   do {
337     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
338     if (olddata_val == NULL)
339       break;
340   } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
341               olddata, olddata_val, NULL)));
342
343   return olddata_val;
344 }
345
346 /**
347  * gst_mini_object_take:
348  * @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
349  *     be replaced
350  * @newdata: pointer to new mini-object
351  *
352  * Modifies a pointer to point to a new mini-object. The modification
353  * is done atomically. This version is similar to gst_mini_object_replace()
354  * except that it does not increase the refcount of @newdata and thus
355  * takes ownership of @newdata.
356  *
357  * Either @newdata and the value pointed to by @olddata may be NULL.
358  *
359  * Returns: TRUE if @newdata was different from @olddata
360  */
361 gboolean
362 gst_mini_object_take (GstMiniObject ** olddata, GstMiniObject * newdata)
363 {
364   GstMiniObject *olddata_val;
365
366   g_return_val_if_fail (olddata != NULL, FALSE);
367
368   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "take %p (%d) with %p (%d)",
369       *olddata, *olddata ? (*olddata)->refcount : 0,
370       newdata, newdata ? newdata->refcount : 0);
371
372   do {
373     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
374     if (G_UNLIKELY (olddata_val == newdata))
375       break;
376   } while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *)
377               olddata, olddata_val, newdata)));
378
379   if (olddata_val)
380     gst_mini_object_unref (olddata_val);
381
382   return olddata_val != newdata;
383 }
384
385 /**
386  * gst_mini_object_weak_ref: (skip)
387  * @object: #GstMiniObject to reference weakly
388  * @notify: callback to invoke before the mini object is freed
389  * @data: extra data to pass to notify
390  *
391  * Adds a weak reference callback to a mini object. Weak references are
392  * used for notification when a mini object is finalized. They are called
393  * "weak references" because they allow you to safely hold a pointer
394  * to the mini object without calling gst_mini_object_ref()
395  * (gst_mini_object_ref() adds a strong reference, that is, forces the object
396  * to stay alive).
397  *
398  * Since: 0.10.35
399  */
400 void
401 gst_mini_object_weak_ref (GstMiniObject * object,
402     GstMiniObjectWeakNotify notify, gpointer data)
403 {
404   guint i;
405
406   g_return_if_fail (object != NULL);
407   g_return_if_fail (notify != NULL);
408   g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
409
410   G_LOCK (qdata_mutex);
411   i = object->n_qdata++;
412   object->qdata =
413       g_realloc (object->qdata, sizeof (object->qdata[0]) * object->n_qdata);
414   object->qdata[i].quark = weak_ref_quark;
415   object->qdata[i].notify = notify;
416   object->qdata[i].data = data;
417   G_UNLOCK (qdata_mutex);
418 }
419
420 /**
421  * gst_mini_object_weak_unref: (skip)
422  * @object: #GstMiniObject to remove a weak reference from
423  * @notify: callback to search for
424  * @data: data to search for
425  *
426  * Removes a weak reference callback to a mini object.
427  *
428  * Since: 0.10.35
429  */
430 void
431 gst_mini_object_weak_unref (GstMiniObject * object,
432     GstMiniObjectWeakNotify notify, gpointer data)
433 {
434   guint i;
435   gboolean found_one = FALSE;
436
437   g_return_if_fail (object != NULL);
438   g_return_if_fail (notify != NULL);
439
440   G_LOCK (qdata_mutex);
441   for (i = 0; i < object->n_qdata; i++) {
442     if (object->qdata[i].quark == weak_ref_quark &&
443         object->qdata[i].notify == notify && object->qdata[i].data == data) {
444       found_one = TRUE;
445       if (--object->n_qdata == 0) {
446         /* we don't shrink but free when everything is gone */
447         g_free (object->qdata);
448         object->qdata = NULL;
449       } else if (i != object->n_qdata)
450         object->qdata[i] = object->qdata[object->n_qdata];
451       break;
452     }
453   }
454   G_UNLOCK (qdata_mutex);
455
456   if (!found_one)
457     g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
458 }
459
460 /**
461  * gst_mini_object_set_qdata:
462  * @object: a #GstMiniObject
463  * @quark: A #GQuark, naming the user data pointer
464  * @data: An opaque user data pointer
465  * @destroy: Function to invoke with @data as argument, when @data
466  *           needs to be freed
467  *
468  * This sets an opaque, named pointer on a miniobject.
469  * The name is specified through a #GQuark (retrived e.g. via
470  * g_quark_from_static_string()), and the pointer
471  * can be gotten back from the @object with gst_mini_object_get_qdata()
472  * until the @object is disposed.
473  * Setting a previously set user data pointer, overrides (frees)
474  * the old pointer set, using #NULL as pointer essentially
475  * removes the data stored.
476  *
477  * @destroy may be specified which is called with @data as argument
478  * when the @object is disposed, or the data is being overwritten by
479  * a call to gst_mini_object_set_qdata() with the same @quark.
480  */
481 void
482 gst_mini_object_set_qdata (GstMiniObject * object, GQuark quark,
483     gpointer data, GDestroyNotify destroy)
484 {
485   guint i;
486   gpointer old_data = NULL;
487   GDestroyNotify old_notify = NULL;
488
489   g_return_if_fail (object != NULL);
490   g_return_if_fail (quark > 0);
491
492   G_LOCK (qdata_mutex);
493   for (i = 0; i < object->n_qdata; i++) {
494     if (object->qdata[i].quark == quark) {
495       old_data = object->qdata[i].data;
496       old_notify = (GDestroyNotify) object->qdata[i].notify;
497
498       if (data == NULL) {
499         /* remove item */
500         if (--object->n_qdata == 0) {
501           /* we don't shrink but free when everything is gone */
502           g_free (object->qdata);
503           object->qdata = NULL;
504         } else if (i != object->n_qdata)
505           object->qdata[i] = object->qdata[object->n_qdata];
506       }
507       break;
508     }
509   }
510   if (!old_data) {
511     /* add item */
512     i = object->n_qdata++;
513     object->qdata =
514         g_realloc (object->qdata, sizeof (object->qdata[0]) * object->n_qdata);
515   }
516   object->qdata[i].quark = quark;
517   object->qdata[i].data = data;
518   object->qdata[i].notify = (GstMiniObjectWeakNotify) destroy;
519   G_UNLOCK (qdata_mutex);
520
521   if (old_notify)
522     old_notify (old_data);
523 }
524
525 /**
526  * gst_mini_object_get_qdata:
527  * @object: The GstMiniObject to get a stored user data pointer from
528  * @quark: A #GQuark, naming the user data pointer
529  *
530  * This function gets back user data pointers stored via
531  * gst_mini_object_set_qdata().
532  *
533  * Returns: (transfer none): The user data pointer set, or %NULL
534  */
535 gpointer
536 gst_mini_object_get_qdata (GstMiniObject * object, GQuark quark)
537 {
538   guint i;
539   gpointer result = NULL;
540
541   g_return_val_if_fail (object != NULL, NULL);
542   g_return_val_if_fail (quark > 0, NULL);
543
544   G_LOCK (qdata_mutex);
545   for (i = 0; i < object->n_qdata; i++) {
546     if (object->qdata[i].quark == quark) {
547       result = object->qdata[i].data;
548       break;
549     }
550   }
551   G_UNLOCK (qdata_mutex);
552
553   return result;
554 }