Some more work on cleanup.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 19 Dec 2001 19:22:53 +0000 (19:22 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 19 Dec 2001 19:22:53 +0000 (19:22 +0000)
Original commit message from CVS:
Some more work on cleanup.
- added two functions in the scheduler _setup and _reset to initialize
the context. In the case of the cothread context we have to map the
cothread stack space onto the threads stack.
- setup/reset the scheduler context in the threads context.
- fix the ghostpad cleanup.
- slightly changed the scheduler code to cleanly remove connections.

gst/Makefile.am
gst/cothreads.c
gst/gstbin.c
gst/gstpad.c
gst/gstpipeline.c
gst/gstscheduler.c
gst/gstscheduler.h
gst/gstthread.c
gst/schedulers/gstbasicscheduler.c

index 4d09d49..b12b325 100644 (file)
@@ -211,9 +211,9 @@ libgst_la_CFLAGS = -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" \
        -Wcast-align -Wsign-compare \
        -Wmissing-prototypes -Wmissing-declarations \
        -Wnested-externs \
-       -Winline -Wno-unused
+       -Winline -Wno-unused 
 
-libgst_la_LIBADD = $(XML_LIBS) $(GLIB_LIBS)
+libgst_la_LIBADD = $(XML_LIBS) $(GLIB_LIBS) 
 
 libgst_la_LDFLAGS = -version-info $(GST_LIBVERSION)
 
index 8bb1bc7..db029a3 100644 (file)
@@ -116,12 +116,14 @@ cothread_free (cothread_context *ctx)
     if (ctx->threads[i]->lock) {
       g_mutex_unlock(ctx->threads[i]->lock);
       g_mutex_free (ctx->threads[i]->lock);
+      ctx->threads[i]->lock = NULL;
     }
 #endif
-    if (i == 0)
+    if (i == 0) {
       g_free (ctx->threads[i]);
+      ctx->threads[i] = NULL;
+    }
   }
-
   g_hash_table_destroy (ctx->data);
   g_free (ctx);
 }
index d697b47..c1a1b00 100644 (file)
@@ -215,6 +215,12 @@ gst_bin_unset_element_sched (GstElement * element)
   g_return_if_fail (element != NULL);
   g_return_if_fail (GST_IS_ELEMENT (element));
 
+  if (GST_ELEMENT_SCHED (element) == NULL) {
+    GST_INFO (GST_CAT_SCHEDULING, "element \"%s\" has no scheduler",
+             GST_ELEMENT_NAME (element));
+    return;
+  }
+  
   GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from it sched %p",
            GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element));
 
@@ -335,11 +341,6 @@ gst_bin_remove (GstBin * bin, GstElement * element)
               GST_ELEMENT_NAME (bin));
     return;
   }
-#ifdef USE_GLIB2
-  g_signal_handlers_disconnect_matched (G_OBJECT (element),
-                                     G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
-                                     gst_bin_child_state_change, bin);
-#endif
 
   /* remove this element from the list of managed elements */
   gst_bin_unset_element_sched (element);
index 1308b18..113f190 100644 (file)
@@ -534,9 +534,11 @@ gst_pad_disconnect (GstPad *srcpad,
   GST_RPAD_PEER(realsrc) = NULL;
   GST_RPAD_PEER(realsink) = NULL;
 
-  // now tell the scheduler
-  if (realsrc->sched)
-    gst_scheduler_pad_disconnect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink);
+  /* now tell the scheduler */
+  if (GST_PAD_PARENT (realsrc)->sched)
+    gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsrc)->sched, (GstPad *)realsrc, (GstPad *)realsink);
+  else if (GST_PAD_PARENT (realsink)->sched)
+    gst_scheduler_pad_disconnect (GST_PAD_PARENT (realsink)->sched, (GstPad *)realsrc, (GstPad *)realsink);
 
   /* fire off a signal to each of the pads telling them that they've been disconnected */
   g_signal_emit(G_OBJECT(realsrc), gst_real_pad_signals[REAL_DISCONNECTED], 0, realsink);
@@ -714,7 +716,8 @@ gst_pad_get_padtemplate (GstPad *pad)
   return GST_PAD_PADTEMPLATE (pad); 
 }
 
-/**
+
+/*
  * gst_pad_set_sched:
  * @pad: the pad to set the scheduler for
  * @sched: The scheduler to set
@@ -726,10 +729,10 @@ gst_pad_set_sched (GstPad *pad, GstScheduler *sched)
 {
   g_return_if_fail (pad != NULL);
   g_return_if_fail (GST_IS_PAD (pad));
-
   GST_RPAD_SCHED(pad) = sched;
 }
-
 /**
  * gst_pad_get_sched:
  * @pad: the pad to get the scheduler from
@@ -743,7 +746,7 @@ gst_pad_get_sched (GstPad *pad)
 {
   g_return_val_if_fail (pad != NULL, NULL);
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
   return GST_RPAD_SCHED(pad);
 }
 
@@ -1036,11 +1039,6 @@ gst_real_pad_dispose (GObject *object)
     gst_pad_disconnect (pad, GST_PAD (GST_PAD_PEER (pad)));
   }
   
-  if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
-    GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
-    gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
-  }
-  
   /* FIXME we should destroy the ghostpads, because they are nothing without the real pad  */
   if (GST_REAL_PAD (pad)->ghostpads) {
     GList *orig, *ghostpads;
@@ -1052,7 +1050,7 @@ gst_real_pad_dispose (GObject *object)
 
       if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){
         GST_DEBUG (GST_CAT_REFCOUNTING, "removing ghost pad from element '%s'\n", GST_OBJECT_NAME(GST_OBJECT_PARENT (ghostpad)));
-        gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), ghostpad);
+        gst_element_remove_ghost_pad (GST_ELEMENT (GST_OBJECT_PARENT (ghostpad)), GST_PAD (ghostpad));
       }
       ghostpads = g_list_next (ghostpads);
     }
@@ -1060,6 +1058,11 @@ gst_real_pad_dispose (GObject *object)
     g_list_free (GST_REAL_PAD(pad)->ghostpads);
   }
 
+  if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))){
+    GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'\n",GST_OBJECT_NAME(GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
+    gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
+  }
+  
   G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
 }
 
@@ -1579,7 +1582,7 @@ gst_pad_select (GList *padlist)
 {
   GstPad *pad;
 
-  pad = gst_scheduler_pad_select (gst_pad_get_sched (GST_PAD (padlist->data)), padlist);
+  pad = gst_scheduler_pad_select (GST_PAD_PARENT (padlist->data)->sched, padlist);
 
   return pad;
 }
index 0a70f22..dd1b459 100644 (file)
@@ -97,15 +97,21 @@ gst_pipeline_class_init (GstPipelineClass *klass)
 static void
 gst_pipeline_init (GstPipeline *pipeline)
 {
+  GstScheduler *scheduler;
+
   /* we're a manager by default */
   GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER);
 
-  GST_ELEMENT_SCHED (pipeline) = gst_schedulerfactory_make ("basic", GST_ELEMENT (pipeline));
+  scheduler = gst_schedulerfactory_make ("basic", GST_ELEMENT (pipeline));
+
+  GST_ELEMENT_SCHED (pipeline) = scheduler;
+
+  gst_object_ref (GST_OBJECT (scheduler));
+  gst_object_sink (GST_OBJECT (scheduler));
 
-  gst_object_ref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
-  gst_object_sink (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
+  gst_scheduler_setup (scheduler);
 
-  GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", GST_ELEMENT_SCHED (pipeline));
+  GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", scheduler);
 }
 
 static void
@@ -115,6 +121,7 @@ gst_pipeline_dispose (GObject *object)
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 
+  gst_scheduler_reset (GST_ELEMENT_SCHED (pipeline));
   gst_object_unref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
 }
 
index 6284ac1..553c520 100644 (file)
@@ -68,6 +68,32 @@ gst_scheduler_init (GstScheduler *sched)
 }
 
 /**
+ * gst_scheduler_setup:
+ * @sched: the schedulerr
+ *
+ * Prepare the scheduler.
+ */
+void
+gst_scheduler_setup (GstScheduler *sched)
+{
+  if (CLASS (sched)->setup)
+    CLASS (sched)->setup (sched);
+}
+
+/**
+ * gst_scheduler_reset:
+ * @sched: the schedulerr
+ *
+ * Reset the scheduler
+ */
+void
+gst_scheduler_reset (GstScheduler *sched)
+{
+  if (CLASS (sched)->reset)
+    CLASS (sched)->reset (sched);
+}
+
+/**
  * gst_scheduler_pad_connect:
  * @sched: the schedulerr
  * @srcpad: the srcpad to connect
index e9a5f35..c60b55c 100644 (file)
@@ -65,6 +65,8 @@ struct _GstScheduler {
 struct _GstSchedulerClass {
   GstObjectClass parent_class;
 
+  void (*setup)                        (GstScheduler *sched);
+  void (*reset)                        (GstScheduler *sched);
   void (*add_element)          (GstScheduler *sched, GstElement *element);
   void (*remove_element)       (GstScheduler *sched, GstElement *element);
   void (*enable_element)       (GstScheduler *sched, GstElement *element);
@@ -84,6 +86,8 @@ GType                 gst_scheduler_get_type          (void);
 
 #define                gst_scheduler_destroy(sched)    gst_object_destroy(GST_OBJECT(sched))
 
+void                   gst_scheduler_setup             (GstScheduler *sched);
+void                   gst_scheduler_reset             (GstScheduler *sched);
 void                   gst_scheduler_add_element       (GstScheduler *sched, GstElement *element);
 void                   gst_scheduler_remove_element    (GstScheduler *sched, GstElement *element);
 void                   gst_scheduler_enable_element    (GstScheduler *sched, GstElement *element);
index 8c91a63..a11bcfe 100644 (file)
@@ -434,6 +434,7 @@ gst_thread_main_loop (void *arg)
 
   g_mutex_lock (thread->lock);
 
+  gst_scheduler_setup (GST_ELEMENT_SCHED (thread));
   GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
 
   thread->pid = getpid();
@@ -549,6 +550,10 @@ gst_thread_main_loop (void *arg)
         break;
     }
   }
+  /* we need to destroy the scheduler here bacause it has mapped it's
+   * stack into the threads stack space */
+  gst_scheduler_reset (GST_ELEMENT_SCHED (thread));
+
   /* since we don't unlock at the end of the while loop, do it here */
   g_mutex_unlock (thread->lock);
 
index c31bc92..f465859 100644 (file)
@@ -46,6 +46,8 @@ static void   gst_basic_scheduler_init                (GstScheduler * scheduler);
 
 static void    gst_basic_scheduler_dispose             (GObject *object);
 
+static void    gst_basic_scheduler_setup               (GstScheduler *sched);
+static void    gst_basic_scheduler_reset               (GstScheduler *sched);
 static void    gst_basic_scheduler_add_element         (GstScheduler *sched, GstElement *element);
 static void     gst_basic_scheduler_remove_element     (GstScheduler *sched, GstElement *element);
 static void     gst_basic_scheduler_enable_element     (GstScheduler *sched, GstElement *element);
@@ -96,6 +98,8 @@ gst_basic_scheduler_class_init (GstSchedulerClass * klass)
 
   gobject_class->dispose       = GST_DEBUG_FUNCPTR (gst_basic_scheduler_dispose);
 
+  klass->setup                         = GST_DEBUG_FUNCPTR (gst_basic_scheduler_setup);
+  klass->reset                 = GST_DEBUG_FUNCPTR (gst_basic_scheduler_reset);
   klass->add_element           = GST_DEBUG_FUNCPTR (gst_basic_scheduler_add_element);
   klass->remove_element        = GST_DEBUG_FUNCPTR (gst_basic_scheduler_remove_element);
   klass->enable_element        = GST_DEBUG_FUNCPTR (gst_basic_scheduler_enable_element);
@@ -116,12 +120,6 @@ gst_basic_scheduler_init (GstScheduler *scheduler)
 static void
 gst_basic_scheduler_dispose (GObject *object)
 {
-  GstScheduler *sched = GST_SCHEDULER (object);
-  cothread_context *ctx;
-
-  ctx = GST_BIN (GST_SCHED_PARENT (sched))->threadcontext;
-
-  cothread_free (ctx);
   
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -407,11 +405,8 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
 
   GST_DEBUG (GST_CAT_SCHEDULING, "chain is using COTHREADS\n");
 
-  /* first create thread context */
-  if (bin->threadcontext == NULL) {
-    GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
-    bin->threadcontext = cothread_init ();
-  }
+  g_assert (bin->threadcontext != NULL);
+
 
   /* walk through all the chain's elements */
   elements = chain->elements;
@@ -785,6 +780,37 @@ gst_basic_scheduler_chain_recursive_add (GstSchedulerChain * chain, GstElement *
  * Entry points for this scheduler.
  */
 static void
+gst_basic_scheduler_setup (GstScheduler *sched)
+{
+  GstBin *bin = GST_BIN (sched->parent);
+
+  /* first create thread context */
+  if (bin->threadcontext == NULL) {
+    GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
+    bin->threadcontext = cothread_init ();
+  }
+}
+
+static void
+gst_basic_scheduler_reset (GstScheduler *sched)
+{
+  cothread_context *ctx;
+  GstBin *bin = GST_BIN (GST_SCHED_PARENT (sched));
+  GList *elements = sched->elements;
+
+  while (elements) {
+    GST_ELEMENT (elements->data)->threadstate = NULL;
+    elements = g_list_next (elements);
+  }
+  
+  ctx = GST_BIN (GST_SCHED_PARENT (sched))->threadcontext;
+
+  cothread_free (ctx);
+  
+  GST_BIN (GST_SCHED_PARENT (sched))->threadcontext = NULL;
+}
+
+static void
 gst_basic_scheduler_add_element (GstScheduler * sched, GstElement * element)
 {
   GList *pads;
@@ -962,10 +988,17 @@ gst_basic_scheduler_pad_disconnect (GstScheduler * sched, GstPad * srcpad, GstPa
    * since they are guaranteed to be in the same chain
    * FIXME is it potentially better to make an attempt at splitting cleaner??
    */
-  chain = gst_basic_scheduler_find_chain (sched, element1);
-  if (chain) {
+  chain1 = gst_basic_scheduler_find_chain (sched, element1);
+  chain2 = gst_basic_scheduler_find_chain (sched, element2);
+
+  if (chain1 != chain2) {
+    GST_INFO (GST_CAT_SCHEDULING, "elements not in the same chain");
+    return;
+  }
+
+  if (chain1) {
     GST_INFO (GST_CAT_SCHEDULING, "destroying chain");
-    gst_basic_scheduler_chain_destroy (chain);
+    gst_basic_scheduler_chain_destroy (chain1);
 
     /* now create a new chain to hold element1 and build it from scratch */
     chain1 = gst_basic_scheduler_chain_new (sched);
@@ -973,7 +1006,10 @@ gst_basic_scheduler_pad_disconnect (GstScheduler * sched, GstPad * srcpad, GstPa
   }
 
   /* check the other element to see if it landed in the newly created chain */
-  if (gst_basic_scheduler_find_chain (sched, element2) == NULL) {
+  if (chain2) {
+    GST_INFO (GST_CAT_SCHEDULING, "destroying chain");
+    gst_basic_scheduler_chain_destroy (chain2);
+
     /* if not in chain, create chain and build from scratch */
     chain2 = gst_basic_scheduler_chain_new (sched);
     gst_basic_scheduler_chain_recursive_add (chain2, element2);