diff --git a/gst/gststructure.c b/gst/gststructure.c index fafaa65c33..4288c4a4ee 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -418,6 +418,47 @@ gst_clear_structure (GstStructure ** structure_ptr) g_clear_pointer (structure_ptr, gst_structure_free); } +/** + * gst_structure_take: + * @oldstr_ptr: (inout) (transfer full) (nullable): pointer to a place of + * a #GstStructure to take + * @newstr: (transfer full) (allow-none): a new #GstStructure + * + * Atomically modifies a pointer to point to a new object. + * The #GstStructure @oldstr_ptr is pointing to is freed and + * @newstr is taken ownership over. + * + * Either @newstr and the value pointed to by @oldstr_ptr may be %NULL. + * + * Returns: %TRUE if @newstr was different from @oldstr_ptr + * + * Since: 1.18 + */ +gboolean +gst_structure_take (GstStructure ** oldstr_ptr, GstStructure * newstr) +{ + GstStructure *oldstr; + + g_return_val_if_fail (oldstr_ptr != NULL, FALSE); + + oldstr = g_atomic_pointer_get ((gpointer *) oldstr_ptr); + + if (G_UNLIKELY (oldstr == newstr)) + return FALSE; + + while (G_UNLIKELY (!g_atomic_pointer_compare_and_exchange ((gpointer *) + oldstr_ptr, oldstr, newstr))) { + oldstr = g_atomic_pointer_get ((gpointer *) oldstr_ptr); + if (G_UNLIKELY (oldstr == newstr)) + break; + } + + if (oldstr) + gst_structure_free (oldstr); + + return oldstr != newstr; +} + /** * gst_structure_get_name: * @structure: a #GstStructure diff --git a/gst/gststructure.h b/gst/gststructure.h index 8df9bc3bb9..a267bc8735 100644 --- a/gst/gststructure.h +++ b/gst/gststructure.h @@ -137,6 +137,9 @@ GST_API void gst_clear_structure (GstStructure **structure_ptr); #define gst_clear_structure(structure_ptr) g_clear_pointer ((structure_ptr), gst_structure_free) +GST_API +gboolean gst_structure_take (GstStructure ** oldstr_ptr, + GstStructure * newstr); GST_API const gchar * gst_structure_get_name (const GstStructure * structure);