#define GST_CLOCK_SLAVE_LOCK(clock) g_mutex_lock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
#define GST_CLOCK_SLAVE_UNLOCK(clock) g_mutex_unlock (&GST_CLOCK_CAST (clock)->priv->slave_lock)
+/* An atomically ref-counted wrapper around a GWeakRef for a GstClock, created
+ * by the clock and shared with all its clock entries.
+ *
+ * This exists because g_weak_ref_ operations are quite expensive and operate
+ * with a global GRWLock. _get takes a reader lock, _init and _clear take a
+ * writer lock. We want to avoid having a GWeakRef in every clock entry.
+ *
+ * FIXME: Simplify this with g_atomic_rc_box_new (GWeakRef) once we can depend
+ * on GLib 2.58.
+ */
+struct _GstClockWeakRef
+{
+ gint refcount;
+ GWeakRef clock;
+};
+
+static GstClockWeakRef *
+gst_clock_weak_ref_new (GstClock * clock)
+{
+ GstClockWeakRef *weakref = g_slice_new (GstClockWeakRef);
+
+ weakref->refcount = 1;
+ g_weak_ref_init (&weakref->clock, clock);
+
+ return weakref;
+}
+
+static GstClockWeakRef *
+gst_clock_weak_ref_ref (GstClockWeakRef * weakref)
+{
+ g_atomic_int_add (&weakref->refcount, 1);
+ return weakref;
+}
+
+static void
+gst_clock_weak_ref_unref (GstClockWeakRef * weakref)
+{
+ gint old_refcount;
+
+ old_refcount = g_atomic_int_add (&weakref->refcount, -1);
+ g_return_if_fail (old_refcount > 0);
+
+ if (G_UNLIKELY (old_refcount == 1)) {
+ g_weak_ref_clear (&weakref->clock);
+ g_slice_free (GstClockWeakRef, weakref);
+ }
+}
+
+static GstClock *
+gst_clock_weak_ref_get (GstClockWeakRef * weakref)
+{
+ return g_weak_ref_get (&weakref->clock);
+}
+
struct _GstClockPrivate
{
GMutex slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
gint post_count;
gboolean synced;
+
+ GstClockWeakRef *weakref;
};
typedef struct _GstClockEntryImpl GstClockEntryImpl;
-#define GST_CLOCK_ENTRY_CLOCK_WEAK_REF(entry) (&((GstClockEntryImpl *)(entry))->clock)
+#define GST_CLOCK_ENTRY_CLOCK_WEAK_REF(entry) (((GstClockEntryImpl *)(entry))->weakref)
/* seqlocks */
#define read_seqbegin(clock) \
entry->_clock = clock;
#endif
#endif
- g_weak_ref_init (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry), clock);
+ GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry) =
+ gst_clock_weak_ref_ref (clock->priv->weakref);
entry->type = type;
entry->time = time;
entry->interval = interval;
if (entry_impl->destroy_entry)
entry_impl->destroy_entry (entry_impl);
- g_weak_ref_clear (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ gst_clock_weak_ref_unref (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
/* FIXME: add tracer hook for struct allocations such as clock entries */
entry = (GstClockEntry *) id;
requested = GST_CLOCK_ENTRY_TIME (entry);
- clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ clock = gst_clock_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
if (G_UNLIKELY (clock == NULL))
goto invalid_entry;
entry = (GstClockEntry *) id;
requested = GST_CLOCK_ENTRY_TIME (entry);
- clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ clock = gst_clock_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
if (G_UNLIKELY (clock == NULL))
goto invalid_entry;
g_return_if_fail (id != NULL);
entry = (GstClockEntry *) id;
- clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ clock = gst_clock_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
if (G_UNLIKELY (clock == NULL))
goto invalid_entry;
priv->timeout = DEFAULT_TIMEOUT;
priv->times = g_new0 (GstClockTime, 4 * priv->window_size);
priv->times_temp = priv->times + 2 * priv->window_size;
+ priv->weakref = gst_clock_weak_ref_new (clock);
}
static void
clock->priv->times_temp = NULL;
GST_CLOCK_SLAVE_UNLOCK (clock);
+ gst_clock_weak_ref_unref (clock->priv->weakref);
g_mutex_clear (&clock->priv->slave_lock);
g_cond_clear (&clock->priv->sync_cond);
g_return_val_if_fail (id != NULL, NULL);
entry = (GstClockEntry *) id;
- return g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ return gst_clock_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
}
/**
g_return_val_if_fail (clock != NULL, FALSE);
entry = (GstClockEntry *) id;
- entry_clock = g_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
+ entry_clock = gst_clock_weak_ref_get (GST_CLOCK_ENTRY_CLOCK_WEAK_REF (entry));
if (entry_clock == clock)
ret = TRUE;