From dead5c2476ff1033c8765764fbe970a084ad888a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 19 Jun 2014 19:16:01 +0100 Subject: [PATCH] multiudpsink: make udp client structure refcounted Use the refcount for memory management and keep track of the number of duplicate clients in a separate variable. This will be useful later, and means we don't have to hold the OBJECT_LOCK all the time. https://bugzilla.gnome.org/show_bug.cgi?id=732866 --- gst/udp/gstmultiudpsink.c | 48 +++++++++++++++++++++++++-------------- gst/udp/gstmultiudpsink.h | 3 ++- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c index be2b964ca8..2b346a1f93 100644 --- a/gst/udp/gstmultiudpsink.c +++ b/gst/udp/gstmultiudpsink.c @@ -411,7 +411,7 @@ gst_multiudpsink_init (GstMultiUDPSink * sink) } static GstUDPClient * -create_client (GstMultiUDPSink * sink, const gchar * host, gint port) +gst_udp_client_new (GstMultiUDPSink * sink, const gchar * host, gint port) { GstUDPClient *client; GInetAddress *addr; @@ -442,7 +442,8 @@ create_client (GstMultiUDPSink * sink, const gchar * host, gint port) #endif client = g_slice_new0 (GstUDPClient); - client->refcount = 1; + client->ref_count = 1; + client->add_count = 0; client->host = g_strdup (host); client->port = port; client->addr = g_inet_socket_address_new (addr, port); @@ -458,12 +459,23 @@ name_resolve: } } +/* call with client lock held */ static void -free_client (GstUDPClient * client) +gst_udp_client_unref (GstUDPClient * client) { - g_object_unref (client->addr); - g_free (client->host); - g_slice_free (GstUDPClient, client); + if (--client->ref_count == 0) { + g_object_unref (client->addr); + g_free (client->host); + g_slice_free (GstUDPClient, client); + } +} + +/* call with client lock held */ +static inline GstUDPClient * +gst_udp_client_ref (GstUDPClient * client) +{ + ++client->ref_count; + return client; } static gint @@ -482,7 +494,7 @@ gst_multiudpsink_finalize (GObject * object) sink = GST_MULTIUDPSINK (object); - g_list_foreach (sink->clients, (GFunc) free_client, NULL); + g_list_foreach (sink->clients, (GFunc) gst_udp_client_unref, NULL); g_list_free (sink->clients); if (sink->socket) @@ -584,7 +596,7 @@ gst_multiudpsink_render (GstBaseSink * bsink, GstBuffer * buffer) else socket = sink->used_socket; - count = sink->send_duplicates ? client->refcount : 1; + count = sink->send_duplicates ? client->add_count : 1; while (count--) { gssize ret; @@ -695,7 +707,7 @@ gst_multiudpsink_get_clients_string (GstMultiUDPSink * sink) clients = g_list_next (clients); - count = client->refcount; + count = client->add_count; while (count--) { g_string_append_printf (str, "%s:%d%s", client->host, client->port, (clients || count > 1 ? "," : "")); @@ -1267,10 +1279,9 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host, family = g_socket_address_get_family (client->addr); GST_DEBUG_OBJECT (sink, "found %d existing clients with host %s, port %d", - client->refcount, host, port); - client->refcount++; + client->add_count, host, port); } else { - client = create_client (sink, host, port); + client = gst_udp_client_new (sink, host, port); if (!client) goto error; @@ -1291,6 +1302,8 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host, ++sink->num_v6_unique; } + ++client->add_count; + if (family == G_SOCKET_FAMILY_IPV4) ++sink->num_v4_all; else @@ -1342,10 +1355,11 @@ gst_multiudpsink_remove (GstMultiUDPSink * sink, const gchar * host, gint port) client = (GstUDPClient *) find->data; GST_DEBUG_OBJECT (sink, "found %d clients with host %s, port %d", - client->refcount, host, port); + client->add_count, host, port); - client->refcount--; - if (client->refcount == 0) { + --client->add_count; + + if (client->add_count == 0) { GInetSocketAddress *saddr = G_INET_SOCKET_ADDRESS (client->addr); GSocketFamily family = g_socket_address_get_family (client->addr); GInetAddress *addr = g_inet_socket_address_get_address (saddr); @@ -1382,7 +1396,7 @@ gst_multiudpsink_remove (GstMultiUDPSink * sink, const gchar * host, gint port) sink->clients = g_list_delete_link (sink->clients, find); - free_client (client); + gst_udp_client_unref (client); } g_mutex_unlock (&sink->client_lock); @@ -1406,7 +1420,7 @@ gst_multiudpsink_clear_internal (GstMultiUDPSink * sink, gboolean lock) * socket or anything to free for UDP */ if (lock) g_mutex_lock (&sink->client_lock); - g_list_foreach (sink->clients, (GFunc) free_client, sink); + g_list_foreach (sink->clients, (GFunc) gst_udp_client_unref, sink); g_list_free (sink->clients); sink->clients = NULL; sink->num_v4_unique = 0; diff --git a/gst/udp/gstmultiudpsink.h b/gst/udp/gstmultiudpsink.h index 60af9587b4..ee9776dde8 100644 --- a/gst/udp/gstmultiudpsink.h +++ b/gst/udp/gstmultiudpsink.h @@ -39,7 +39,8 @@ typedef struct _GstMultiUDPSink GstMultiUDPSink; typedef struct _GstMultiUDPSinkClass GstMultiUDPSinkClass; typedef struct { - gint refcount; + gint ref_count; /* for memory management */ + gint add_count; /* how often this address has been added */ GSocketAddress *addr; gchar *host;