59
67
/* Mutex used for weak referencing */
60
G_LOCK_DEFINE_STATIC (weak_refs_mutex);
68
G_LOCK_DEFINE_STATIC (qdata_mutex);
69
static GQuark weak_ref_quark;
71
#define SHARE_ONE (1 << 16)
72
#define SHARE_TWO (2 << 16)
73
#define SHARE_MASK (~(SHARE_ONE - 1))
74
#define IS_SHARED(state) (state >= SHARE_TWO)
75
#define LOCK_ONE (GST_LOCK_FLAG_LAST)
76
#define FLAG_MASK (GST_LOCK_FLAG_LAST - 1)
77
#define LOCK_MASK ((SHARE_ONE - 1) - FLAG_MASK)
78
#define LOCK_FLAG_MASK (SHARE_ONE - 1)
83
GstMiniObjectNotify notify;
85
GDestroyNotify destroy;
88
#define QDATA(o,i) ((GstQData *)(o)->qdata)[(i)]
89
#define QDATA_QUARK(o,i) (QDATA(o,i).quark)
90
#define QDATA_NOTIFY(o,i) (QDATA(o,i).notify)
91
#define QDATA_DATA(o,i) (QDATA(o,i).data)
92
#define QDATA_DESTROY(o,i) (QDATA(o,i).destroy)
63
95
_priv_gst_mini_object_initialize (void)
97
weak_ref_quark = g_quark_from_static_string ("GstMiniObjectWeakRefQuark");
65
99
#ifndef GST_DISABLE_TRACE
66
100
_gst_mini_object_trace = _gst_alloc_trace_register ("GstMiniObject", 0);
71
* gst_mini_object_init:
72
* @mini_object: a #GstMiniObject
105
* gst_mini_object_init: (skip)
106
* @mini_object: a #GstMiniObject
73
107
* @type: the #GType of the mini-object to create
74
* @size: the size of the data
76
* Initializes a mini-object with the desired type and size.
80
* Returns: (transfer full): the new mini-object.
108
* @copy_func: the copy function, or NULL
109
* @dispose_func: the dispose function, or NULL
110
* @free_func: the free function or NULL
112
* Initializes a mini-object with the desired type and copy/dispose/free
83
gst_mini_object_init (GstMiniObject * mini_object, GType type, gsize size)
116
gst_mini_object_init (GstMiniObject * mini_object, guint flags, GType type,
117
GstMiniObjectCopyFunction copy_func,
118
GstMiniObjectDisposeFunction dispose_func,
119
GstMiniObjectFreeFunction free_func)
85
121
mini_object->type = type;
86
122
mini_object->refcount = 1;
87
mini_object->flags = 0;
88
mini_object->size = size;
89
mini_object->n_weak_refs = 0;
90
mini_object->weak_refs = NULL;
123
mini_object->lockstate =
124
(flags & GST_MINI_OBJECT_FLAG_LOCK_READONLY ? GST_LOCK_FLAG_READ : 0);
125
mini_object->flags = flags;
127
mini_object->copy = copy_func;
128
mini_object->dispose = dispose_func;
129
mini_object->free = free_func;
131
mini_object->n_qdata = 0;
132
mini_object->qdata = NULL;
92
134
#ifndef GST_DISABLE_TRACE
93
135
_gst_alloc_trace_new (_gst_mini_object_trace, mini_object);
165
* gst_mini_object_lock:
166
* @object: the mini-object to lock
167
* @flags: #GstLockFlags
169
* Lock the mini-object with the specified access mode in @flags.
171
* Returns: %TRUE if @object could be locked.
174
gst_mini_object_lock (GstMiniObject * object, GstLockFlags flags)
176
gint access_mode, state, newstate;
178
g_return_val_if_fail (object != NULL, FALSE);
179
g_return_val_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object), FALSE);
182
access_mode = flags & FLAG_MASK;
183
newstate = state = g_atomic_int_get (&object->lockstate);
185
GST_CAT_TRACE (GST_CAT_LOCKING, "lock %p: state %08x, access_mode %d",
186
object, state, access_mode);
188
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
190
newstate += SHARE_ONE;
191
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
195
/* shared counter > 1 and write access is not allowed */
196
if (access_mode & GST_LOCK_FLAG_WRITE && IS_SHARED (state))
199
if ((state & LOCK_FLAG_MASK) == 0) {
200
/* nothing mapped, set access_mode */
201
newstate |= access_mode;
203
/* access_mode must match */
204
if ((state & access_mode) != access_mode)
207
/* increase refcount */
208
newstate += LOCK_ONE;
210
} while (!g_atomic_int_compare_and_exchange (&object->lockstate, state,
217
GST_CAT_DEBUG (GST_CAT_LOCKING,
218
"lock failed %p: state %08x, access_mode %d", object, state,
225
* gst_mini_object_unlock:
226
* @object: the mini-object to unlock
227
* @flags: #GstLockFlags
229
* Unlock the mini-object with the specified access mode in @flags.
232
gst_mini_object_unlock (GstMiniObject * object, GstLockFlags flags)
234
gint access_mode, state, newstate;
236
g_return_if_fail (object != NULL);
237
g_return_if_fail (GST_MINI_OBJECT_IS_LOCKABLE (object));
240
access_mode = flags & FLAG_MASK;
241
newstate = state = g_atomic_int_get (&object->lockstate);
243
GST_CAT_TRACE (GST_CAT_LOCKING, "unlock %p: state %08x, access_mode %d",
244
object, state, access_mode);
246
if (access_mode & GST_LOCK_FLAG_EXCLUSIVE) {
248
g_return_if_fail (state >= SHARE_ONE);
249
newstate -= SHARE_ONE;
250
access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
254
g_return_if_fail ((state & access_mode) == access_mode);
255
/* decrease the refcount */
256
newstate -= LOCK_ONE;
257
/* last refcount, unset access_mode */
258
if ((newstate & LOCK_FLAG_MASK) == access_mode)
259
newstate &= ~LOCK_FLAG_MASK;
261
} while (!g_atomic_int_compare_and_exchange (&object->lockstate, state,
123
266
* gst_mini_object_is_writable:
124
267
* @mini_object: the mini-object to check
126
* Checks if a mini-object is writable. A mini-object is writable
127
* if the reference count is one. Modification of a mini-object should
128
* only be done after verifying that it is writable.
269
* If @mini_object has the LOCKABLE flag set, check if the current EXCLUSIVE
270
* lock on @object is the only one, this means that changes to the object will
271
* not be visible to any other object.
273
* If the LOCKABLE flag is not set, check if the refcount of @mini_object is
274
* exactly 1, meaning that no other reference exists to the object and that the
275
* object is therefore writable.
277
* Modification of a mini-object should only be done after verifying that it
132
280
* Returns: TRUE if the object is writable.
135
283
gst_mini_object_is_writable (const GstMiniObject * mini_object)
137
287
g_return_val_if_fail (mini_object != NULL, FALSE);
139
return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
289
if (GST_MINI_OBJECT_IS_LOCKABLE (mini_object)) {
290
result = (g_atomic_int_get (&mini_object->lockstate) & SHARE_MASK) < 2;
292
result = (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1);
205
360
return mini_object;
209
weak_refs_notify (GstMiniObject * obj)
213
for (i = 0; i < obj->n_weak_refs; i++)
214
obj->weak_refs[i].notify (obj->weak_refs[i].data, obj);
215
g_free (obj->weak_refs);
364
find_notify (GstMiniObject * object, GQuark quark, gboolean match_notify,
365
GstMiniObjectNotify notify, gpointer data)
369
for (i = 0; i < object->n_qdata; i++) {
370
if (QDATA_QUARK (object, i) == quark) {
371
/* check if we need to match the callback too */
372
if (!match_notify || (QDATA_NOTIFY (object, i) == notify &&
373
QDATA_DATA (object, i) == data))
381
remove_notify (GstMiniObject * object, gint index)
384
if (--object->n_qdata == 0) {
385
/* we don't shrink but free when everything is gone */
386
g_free (object->qdata);
387
object->qdata = NULL;
388
} else if (index != object->n_qdata)
389
QDATA (object, index) = QDATA (object, object->n_qdata);
393
set_notify (GstMiniObject * object, gint index, GQuark quark,
394
GstMiniObjectNotify notify, gpointer data, GDestroyNotify destroy)
398
index = object->n_qdata++;
400
g_realloc (object->qdata, sizeof (GstQData) * object->n_qdata);
402
QDATA_QUARK (object, index) = quark;
403
QDATA_NOTIFY (object, index) = notify;
404
QDATA_DATA (object, index) = data;
405
QDATA_DESTROY (object, index) = destroy;
409
call_finalize_notify (GstMiniObject * obj)
413
for (i = 0; i < obj->n_qdata; i++) {
414
if (QDATA_QUARK (obj, i) == weak_ref_quark)
415
QDATA_NOTIFY (obj, i) (QDATA_DATA (obj, i), obj);
416
if (QDATA_DESTROY (obj, i))
417
QDATA_DESTROY (obj, i) (QDATA_DATA (obj, i));
385
592
* to the mini object without calling gst_mini_object_ref()
386
593
* (gst_mini_object_ref() adds a strong reference, that is, forces the object
387
594
* to stay alive).
392
597
gst_mini_object_weak_ref (GstMiniObject * object,
393
GstMiniObjectWeakNotify notify, gpointer data)
598
GstMiniObjectNotify notify, gpointer data)
397
600
g_return_if_fail (object != NULL);
398
601
g_return_if_fail (notify != NULL);
399
602
g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
401
G_LOCK (weak_refs_mutex);
403
if (object->n_weak_refs) {
404
/* Don't add the weak reference if it already exists. */
405
for (i = 0; i < object->n_weak_refs; i++) {
406
if (object->weak_refs[i].notify == notify &&
407
object->weak_refs[i].data == data) {
408
g_warning ("%s: Attempt to re-add existing weak ref %p(%p) failed.",
409
G_STRFUNC, notify, data);
414
i = object->n_weak_refs++;
416
g_realloc (object->weak_refs, sizeof (object->weak_refs[0]) * i);
418
object->weak_refs = g_malloc0 (sizeof (object->weak_refs[0]));
419
object->n_weak_refs = 1;
422
object->weak_refs[i].notify = notify;
423
object->weak_refs[i].data = data;
425
G_UNLOCK (weak_refs_mutex);
604
G_LOCK (qdata_mutex);
605
set_notify (object, -1, weak_ref_quark, notify, data, NULL);
606
G_UNLOCK (qdata_mutex);
431
612
* @notify: callback to search for
432
613
* @data: data to search for
434
* Removes a weak reference callback to a mini object.
615
* Removes a weak reference callback from a mini object.
439
618
gst_mini_object_weak_unref (GstMiniObject * object,
440
GstMiniObjectWeakNotify notify, gpointer data)
619
GstMiniObjectNotify notify, gpointer data)
442
gboolean found_one = FALSE;
444
623
g_return_if_fail (object != NULL);
445
624
g_return_if_fail (notify != NULL);
447
G_LOCK (weak_refs_mutex);
449
if (object->n_weak_refs) {
452
for (i = 0; i < object->n_weak_refs; i++)
453
if (object->weak_refs[i].notify == notify &&
454
object->weak_refs[i].data == data) {
456
object->n_weak_refs -= 1;
457
if (i != object->n_weak_refs)
458
object->weak_refs[i] = object->weak_refs[object->n_weak_refs];
463
G_UNLOCK (weak_refs_mutex);
626
G_LOCK (qdata_mutex);
627
if ((i = find_notify (object, weak_ref_quark, TRUE, notify, data)) != -1) {
628
remove_notify (object, i);
465
630
g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
632
G_UNLOCK (qdata_mutex);
636
* gst_mini_object_set_qdata:
637
* @object: a #GstMiniObject
638
* @quark: A #GQuark, naming the user data pointer
639
* @data: An opaque user data pointer
640
* @destroy: Function to invoke with @data as argument, when @data
643
* This sets an opaque, named pointer on a miniobject.
644
* The name is specified through a #GQuark (retrived e.g. via
645
* g_quark_from_static_string()), and the pointer
646
* can be gotten back from the @object with gst_mini_object_get_qdata()
647
* until the @object is disposed.
648
* Setting a previously set user data pointer, overrides (frees)
649
* the old pointer set, using #NULL as pointer essentially
650
* removes the data stored.
652
* @destroy may be specified which is called with @data as argument
653
* when the @object is disposed, or the data is being overwritten by
654
* a call to gst_mini_object_set_qdata() with the same @quark.
657
gst_mini_object_set_qdata (GstMiniObject * object, GQuark quark,
658
gpointer data, GDestroyNotify destroy)
661
gpointer old_data = NULL;
662
GDestroyNotify old_notify = NULL;
664
g_return_if_fail (object != NULL);
665
g_return_if_fail (quark > 0);
667
G_LOCK (qdata_mutex);
668
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) {
670
old_data = QDATA_DATA (object, i);
671
old_notify = QDATA_DESTROY (object, i);
674
remove_notify (object, i);
677
set_notify (object, i, quark, NULL, data, destroy);
678
G_UNLOCK (qdata_mutex);
681
old_notify (old_data);
685
* gst_mini_object_get_qdata:
686
* @object: The GstMiniObject to get a stored user data pointer from
687
* @quark: A #GQuark, naming the user data pointer
689
* This function gets back user data pointers stored via
690
* gst_mini_object_set_qdata().
692
* Returns: (transfer none): The user data pointer set, or %NULL
695
gst_mini_object_get_qdata (GstMiniObject * object, GQuark quark)
700
g_return_val_if_fail (object != NULL, NULL);
701
g_return_val_if_fail (quark > 0, NULL);
703
G_LOCK (qdata_mutex);
704
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1)
705
result = QDATA_DATA (object, i);
708
G_UNLOCK (qdata_mutex);
714
* gst_mini_object_steal_qdata:
715
* @object: The GstMiniObject to get a stored user data pointer from
716
* @quark: A #GQuark, naming the user data pointer
718
* This function gets back user data pointers stored via gst_mini_object_set_qdata()
719
* and removes the data from @object without invoking its destroy() function (if
722
* Returns: (transfer full): The user data pointer set, or %NULL
725
gst_mini_object_steal_qdata (GstMiniObject * object, GQuark quark)
730
g_return_val_if_fail (object != NULL, NULL);
731
g_return_val_if_fail (quark > 0, NULL);
733
G_LOCK (qdata_mutex);
734
if ((i = find_notify (object, quark, FALSE, NULL, NULL)) != -1) {
735
result = QDATA_DATA (object, i);
736
remove_notify (object, i);
740
G_UNLOCK (qdata_mutex);