[farsight2/master] Protect the udpports list in the rawudp transmitter

Olivier Crête olivier.crete at collabora.co.uk
Sun Dec 28 12:47:39 PST 2008


---
 transmitters/rawudp/fs-rawudp-transmitter.c |   70 ++++++++++++++++++++++-----
 1 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/transmitters/rawudp/fs-rawudp-transmitter.c b/transmitters/rawudp/fs-rawudp-transmitter.c
index 900437e..051c58a 100644
--- a/transmitters/rawudp/fs-rawudp-transmitter.c
+++ b/transmitters/rawudp/fs-rawudp-transmitter.c
@@ -87,6 +87,8 @@ struct _FsRawUdpTransmitterPrivate
   GstElement **udpsrc_funnels;
   GstElement **udpsink_tees;
 
+  GMutex *mutex;
+  /* Protected by the mutex */
   GList **udpports;
 
   gboolean disposed;
@@ -206,6 +208,7 @@ fs_rawudp_transmitter_init (FsRawUdpTransmitter *self)
   self->priv->disposed = FALSE;
 
   self->components = 2;
+  self->priv->mutex = g_mutex_new ();
 }
 
 static void
@@ -415,6 +418,8 @@ fs_rawudp_transmitter_finalize (GObject *object)
     self->priv->udpports = NULL;
   }
 
+  g_mutex_free (self->priv->mutex);
+
   parent_class->finalize (object);
 }
 
@@ -496,6 +501,7 @@ fs_rawudp_transmitter_new_stream_transmitter (FsTransmitter *transmitter,
  */
 
 struct _UdpPort {
+  /* Protected by the transmitter mutex */
   gint refcount;
 
   GstElement *udpsrc;
@@ -694,24 +700,15 @@ _create_sinksource (
 }
 
 
-UdpPort *
-fs_rawudp_transmitter_get_udpport (FsRawUdpTransmitter *trans,
+static UdpPort *
+fs_rawudp_transmitter_get_udpport_locked (FsRawUdpTransmitter *trans,
     guint component_id,
     const gchar *requested_ip,
-    guint requested_port,
-    GError **error)
+    guint requested_port)
 {
   UdpPort *udpport;
   GList *udpport_e;
 
-  /* First lets check if we already have one */
-  if (component_id > trans->components)
-  {
-    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
-        "Invalid component %d > %d", component_id, trans->components);
-    return NULL;
-  }
-
   for (udpport_e = g_list_first (trans->priv->udpports[component_id]);
        udpport_e;
        udpport_e = g_list_next (udpport_e))
@@ -728,6 +725,36 @@ fs_rawudp_transmitter_get_udpport (FsRawUdpTransmitter *trans,
     }
   }
 
+  return NULL;
+}
+
+
+UdpPort *
+fs_rawudp_transmitter_get_udpport (FsRawUdpTransmitter *trans,
+    guint component_id,
+    const gchar *requested_ip,
+    guint requested_port,
+    GError **error)
+{
+  UdpPort *udpport;
+  UdpPort *tmpudpport;
+
+  /* First lets check if we already have one */
+  if (component_id > trans->components)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
+        "Invalid component %d > %d", component_id, trans->components);
+    return NULL;
+  }
+
+  g_mutex_lock (trans->priv->mutex);
+  udpport = fs_rawudp_transmitter_get_udpport_locked (trans, component_id,
+      requested_ip, requested_port);
+  g_mutex_unlock (trans->priv->mutex);
+
+  if (udpport)
+    return udpport;
+
   GST_DEBUG ("Make new UdpPort for component %u requesting %s:%u", component_id,
       requested_ip ? requested_ip : "ANY", requested_port);
 
@@ -771,8 +798,22 @@ fs_rawudp_transmitter_get_udpport (FsRawUdpTransmitter *trans,
       "sync", FALSE,
       NULL);
 
+  g_mutex_lock (trans->priv->mutex);
+
+  /* Check if someone else added the same port at the same time */
+  tmpudpport = fs_rawudp_transmitter_get_udpport_locked (trans, component_id,
+      requested_ip, requested_port);
+
+  if (tmpudpport)
+  {
+    g_mutex_unlock (trans->priv->mutex);
+    fs_rawudp_transmitter_put_udpport (trans, udpport);
+    return tmpudpport;
+  }
+
   trans->priv->udpports[component_id] =
     g_list_prepend (trans->priv->udpports[component_id], udpport);
+  g_mutex_unlock (trans->priv->mutex);
 
   return udpport;
 
@@ -788,15 +829,20 @@ fs_rawudp_transmitter_put_udpport (FsRawUdpTransmitter *trans,
 {
   GST_LOG ("Put port refcount %d->%d", udpport->refcount, udpport->refcount-1);
 
+  g_mutex_lock (trans->priv->mutex);
+
   if (udpport->refcount > 1)
   {
     udpport->refcount--;
+    g_mutex_unlock (trans->priv->mutex);
     return;
   }
 
   trans->priv->udpports[udpport->component_id] =
     g_list_remove (trans->priv->udpports[udpport->component_id], udpport);
 
+  g_mutex_unlock (trans->priv->mutex);
+
   if (udpport->udpsrc)
   {
     GstStateChangeReturn ret;
-- 
1.5.6.5




More information about the farsight-commits mailing list