Reworked the GstThread implementation, make more operations threadsafe and more reliable.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 6 Sep 2004 15:57:11 +0000 (15:57 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 6 Sep 2004 15:57:11 +0000 (15:57 +0000)
Original commit message from CVS:
* gst/gstthread.c: (gst_thread_dispose), (gst_thread_sync),
(gst_thread_change_state), (gst_thread_child_state_change),
(gst_thread_main_loop):
* gst/gstthread.h:
* testsuite/threads/Makefile.am:
* testsuite/threads/queue.c:
* testsuite/threads/thread.c: (construct_pipeline), (change_state),
(main):
* testsuite/threads/threadc.c: (construct_pipeline):
* testsuite/threads/threadd.c: (main):
* testsuite/threads/threade.c: (main):
* testsuite/threads/threadf.c:
Reworked the GstThread implementation, make more operations
threadsafe and more reliable.
Moved testcases from the failing to the working list.

16 files changed:
gst/gstthread.c
gst/gstthread.h
tests/old/testsuite/threads/Makefile.am
tests/old/testsuite/threads/queue.c
tests/old/testsuite/threads/thread.c
tests/old/testsuite/threads/threadc.c
tests/old/testsuite/threads/threadd.c
tests/old/testsuite/threads/threade.c
tests/old/testsuite/threads/threadf.c
testsuite/threads/Makefile.am
testsuite/threads/queue.c
testsuite/threads/thread.c
testsuite/threads/threadc.c
testsuite/threads/threadd.c
testsuite/threads/threade.c
testsuite/threads/threadf.c

index bc7b1f7..3f07c5b 100644 (file)
@@ -74,8 +74,7 @@ static GstElementStateReturn gst_thread_change_state (GstElement * element);
 static void gst_thread_child_state_change (GstBin * bin,
     GstElementState oldstate, GstElementState newstate, GstElement * element);
 
-static void gst_thread_catch (GstThread * thread);
-static void gst_thread_release (GstThread * thread);
+static void gst_thread_sync (GstThread * thread);
 
 #ifndef GST_DISABLE_LOADSAVE
 static xmlNodePtr gst_thread_save_thyself (GstObject * object,
@@ -225,6 +224,27 @@ gst_thread_dispose (GObject * object)
 
   GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "GstThread: dispose, freeing locks");
 
+  if (thread->thread_id != NULL) {
+    /* thread is still alive */
+    g_mutex_lock (thread->lock);
+    /* thread can be spinning or waiting */
+    GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
+    GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING);
+
+    if (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_WAITING)) {
+      GST_DEBUG_OBJECT (thread, "wait");
+      g_cond_wait (thread->cond, thread->lock);
+      GST_DEBUG_OBJECT (thread, "done");
+    }
+    /* now wait for the thread to destroy itself */
+    GST_DEBUG_OBJECT (thread, "signal");
+    g_cond_signal (thread->cond);
+    GST_DEBUG_OBJECT (thread, "wait");
+    g_cond_wait (thread->cond, thread->lock);
+    GST_DEBUG_OBJECT (thread, "done");
+    g_mutex_unlock (thread->lock);
+  }
+
   g_mutex_free (thread->lock);
   g_cond_free (thread->cond);
 
@@ -362,51 +382,52 @@ gst_thread_release_children_locks (GstThread * thread)
   }
 }
 
-/* stops the main thread, if there is one and grabs the thread's mutex */
+/* sync the main thread, if there is one and makes sure that the thread
+ * is not spinning and in the waiting state. We can only do this if
+ * this function is not called from the thread itself. 
+ *
+ * This function should be called with the thread lock held.
+ */
 static void
-gst_thread_catch (GstThread * thread)
+gst_thread_sync (GstThread * thread)
 {
-  gboolean wait;
+  if (thread->thread_id == NULL)
+    return;
+
+  /* need to stop spinning in any case */
+  GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
 
   if (thread == gst_thread_get_current ()) {
-    /* we're trying to catch ourself */
-    if (!GST_FLAG_IS_SET (thread, GST_THREAD_MUTEX_LOCKED)) {
-      GST_DEBUG_OBJECT (thread, "catching itself, grabbing lock");
-      g_mutex_lock (thread->lock);
-      GST_FLAG_SET (thread, GST_THREAD_MUTEX_LOCKED);
-    }
-    GST_DEBUG_OBJECT (thread, "catching itself");
-    GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
+    /* we're trying to sync ourself. Not much we can do here but hope
+     * that the thread will stop spinning and  end up in the waiting
+     * state */
+    GST_DEBUG_OBJECT (thread, "syncing itself");
   } else {
-    GST_DEBUG_OBJECT (thread, "catching thread, grabbing lock");
-    /* another thread is trying to catch us */
-    g_mutex_lock (thread->lock);
-    wait = !GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING);
-    while (!wait) {
+    GST_DEBUG_OBJECT (thread, "syncing thread, grabbing lock");
+    /* another thread is trying to sync us. The strategy is to 
+     * repeadetly unlock the element locks until the thread is 
+     * blocking in the waiting state. We use a timeout because
+     * unlocking all of the children at the same time is not
+     * atomic and might fail. */
+    while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_WAITING)) {
       GTimeVal tv;
 
-      GST_LOG_OBJECT (thread, "catching thread...");
-      GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
-      g_cond_signal (thread->cond);
+      GST_LOG_OBJECT (thread, "syncing thread...");
+
+      /* release child locks */
       gst_thread_release_children_locks (thread);
       g_get_current_time (&tv);
-      g_time_val_add (&tv, 1000);       /* wait a millisecond to catch the thread */
-      wait = g_cond_timed_wait (thread->cond, thread->lock, &tv);
+      g_time_val_add (&tv, 1000);       /* wait a millisecond to sync the thread */
+      GST_DEBUG_OBJECT (thread, "wait");
+      g_cond_timed_wait (thread->cond, thread->lock, &tv);
     }
     GST_LOG_OBJECT (thread, "caught thread");
+    /* at this point we should be waiting */
+    g_assert (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_WAITING));
   }
   g_assert (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING));
 }
 
-static void
-gst_thread_release (GstThread * thread)
-{
-  if (thread != gst_thread_get_current ()) {
-    g_cond_signal (thread->cond);
-    g_mutex_unlock (thread->lock);
-  }
-}
-
 static GstElementStateReturn
 gst_thread_change_state (GstElement * element)
 {
@@ -415,15 +436,19 @@ gst_thread_change_state (GstElement * element)
   gint transition;
 
   g_return_val_if_fail (GST_IS_THREAD (element), GST_STATE_FAILURE);
-  transition = GST_STATE_TRANSITION (element);
-
-  thread = GST_THREAD (element);
 
   GST_DEBUG_OBJECT (element, "changing state from %s to %s",
       gst_element_state_get_name (GST_STATE (element)),
       gst_element_state_get_name (GST_STATE_PENDING (element)));
 
-  gst_thread_catch (thread);
+  transition = GST_STATE_TRANSITION (element);
+
+  thread = GST_THREAD (element);
+
+  GST_LOG_OBJECT (thread, "grabbing lock");
+  g_mutex_lock (thread->lock);
+
+  gst_thread_sync (thread);
 
   /* FIXME: (or GStreamers ideas about "threading"): the element variables are
      commonly accessed by multiple threads at the same time (see bug #111146
@@ -436,6 +461,7 @@ gst_thread_change_state (GstElement * element)
     case GST_STATE_NULL_TO_READY:
       /* create the thread */
       GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
+      GST_LOG_OBJECT (element, "grabbing lock");
       thread->thread_id = g_thread_create_full (gst_thread_main_loop,
           thread, STACK_SIZE, FALSE, TRUE, thread->priority, NULL);
       if (!thread->thread_id) {
@@ -460,12 +486,13 @@ gst_thread_change_state (GstElement * element)
         elements = g_list_next (elements);
       }
       /* reset self to spinning */
-      if (thread == gst_thread_get_current ())
-        GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
+      GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
       break;
     }
     case GST_STATE_PLAYING_TO_PAUSED:
     {
+      GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
+
       GList *elements = (GList *) gst_bin_get_list (GST_BIN (thread));
 
       while (elements) {
@@ -476,12 +503,14 @@ gst_thread_change_state (GstElement * element)
       break;
     }
     case GST_STATE_PAUSED_TO_READY:
+      GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
       break;
     case GST_STATE_READY_TO_NULL:
       /* we can't join the threads here, because this could have been triggered
          by ourself (ouch) */
       GST_LOG_OBJECT (thread, "destroying GThread %p", thread->thread_id);
       GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING);
+      GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
       /* thread was already gone */
       if (thread->thread_id != NULL) {
         thread->thread_id = NULL;
@@ -492,10 +521,10 @@ gst_thread_change_state (GstElement * element)
               GST_ELEMENT_NAME (thread));
           gst_scheduler_reset (GST_ELEMENT_SCHED (thread));
 
-          /* unlock and signal - we are out, note that gst_thread_release does
-           * nothing when we are running in the thread context */
-          GST_DEBUG_OBJECT (thread, "releasing lock");
+          /* unlock and signal - we are out */
+          GST_DEBUG_OBJECT (thread, "signal");
           g_cond_signal (thread->cond);
+          GST_DEBUG_OBJECT (thread, "unlock");
           g_mutex_unlock (thread->lock);
 
           GST_INFO_OBJECT (thread, "GThread %p is exiting", g_thread_self ());
@@ -504,19 +533,22 @@ gst_thread_change_state (GstElement * element)
 
           g_thread_exit (NULL);
           return GST_STATE_SUCCESS;
+        } else {
+          /* now wait for the thread to destroy itself */
+          GST_DEBUG_OBJECT (thread, "signal");
+          g_cond_signal (thread->cond);
+          GST_DEBUG_OBJECT (thread, "wait");
+          g_cond_wait (thread->cond, thread->lock);
+          GST_DEBUG_OBJECT (thread, "done");
+          /* it should be dead now */
         }
-        /* now wait for the thread to destroy itself */
-        GST_DEBUG_OBJECT (thread, "signal");
-        g_cond_signal (thread->cond);
-        GST_DEBUG_OBJECT (thread, "wait");
-        g_cond_wait (thread->cond, thread->lock);
-        GST_DEBUG_OBJECT (thread, "done");
-        /* it should be dead now */
       }
       break;
     default:
       break;
   }
+  GST_LOG_OBJECT (thread, "unlocking lock");
+  g_mutex_unlock (thread->lock);
 
   if (GST_ELEMENT_CLASS (parent_class)->change_state) {
     ret = GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT (thread));
@@ -524,7 +556,6 @@ gst_thread_change_state (GstElement * element)
     ret = GST_STATE_SUCCESS;
   }
 
-  gst_thread_release (thread);
   return ret;
 
 error_out:
@@ -532,29 +563,60 @@ error_out:
       gst_element_state_get_name (GST_STATE (element)),
       gst_element_state_get_name (GST_STATE_PENDING (element)),
       GST_ELEMENT_NAME (element));
-  gst_thread_release (thread);
+
+  g_mutex_unlock (thread->lock);
+
   return GST_STATE_FAILURE;
 }
 
-/* state changes work this way: We grab the lock and stop the thread from 
-   spinning (via gst_thread_catch) - then we change the state. After that the
-   thread may spin on. */
+/* When a child changes its state the thread might have to start.
+ *
+ * When we are in the thread context we set the spinning flag.
+ * When we are not in the thread context, we grab the lock. The
+ * thread can then only be in the waiting or spinning state. If it's
+ * waiting we signal it to start. If it was spinning, we let it spin.
+ */
 static void
 gst_thread_child_state_change (GstBin * bin, GstElementState oldstate,
     GstElementState newstate, GstElement * element)
 {
+  GstThread *thread = GST_THREAD (bin);
+
   GST_LOG_OBJECT (bin, "(from thread %s) child %s changed state from %s to %s",
       gst_thread_get_current ()? GST_ELEMENT_NAME (gst_thread_get_current ()) :
       "(none)", GST_ELEMENT_NAME (element),
       gst_element_state_get_name (oldstate),
       gst_element_state_get_name (newstate));
+
   if (parent_class->child_state_change)
     parent_class->child_state_change (bin, oldstate, newstate, element);
-  /* We'll wake up the main thread now. Note that we can't lock the thread here,
-     because we might be called from inside gst_thread_change_state when holding
-     the lock. But this doesn't cause any problems. */
-  if (newstate == GST_STATE_PLAYING)
-    g_cond_signal (GST_THREAD (bin)->cond);
+
+  /* see if we have to wake up the thread now. */
+  if (thread == gst_thread_get_current ()) {
+    GST_LOG_OBJECT (element, "we are in the thread context");
+    /* we are the thread, set the spinning flag so that we start spinning
+     * next time */
+    if (newstate == GST_STATE_PLAYING) {
+      GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
+    }
+  } else {
+    g_mutex_lock (thread->lock);
+    /* thread is now spinning or waiting after grabbing the lock */
+    if (newstate == GST_STATE_PLAYING) {
+      if (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_WAITING)) {
+        /* its spinning, that's not really a problem, it will
+         * continue to do so */
+        GST_LOG_OBJECT (element, "thread is playing");
+      } else {
+        /* waiting, set spinning flag and trigger restart. */
+        GST_LOG_OBJECT (element, "signal playing");
+        GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
+        g_cond_signal (GST_THREAD (bin)->cond);
+      }
+    }
+    g_mutex_unlock (thread->lock);
+  }
+  GST_LOG_OBJECT (element, "done child state change");
 }
 
 /**
@@ -568,11 +630,13 @@ static void *
 gst_thread_main_loop (void *arg)
 {
   GstThread *thread = NULL;
-  gboolean status;
+  GstElement *element = NULL;
   GstScheduler *sched;
 
   thread = GST_THREAD (arg);
+  GST_LOG_OBJECT (element, "grabbing lock");
   g_mutex_lock (thread->lock);
+  element = GST_ELEMENT (arg);
   GST_LOG_OBJECT (thread, "Started main loop");
 
   /* initialize gst_thread_current */
@@ -581,32 +645,49 @@ gst_thread_main_loop (void *arg)
   /* set up the element's scheduler */
   gst_scheduler_setup (GST_ELEMENT_SCHED (thread));
   GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
+  GST_FLAG_UNSET (thread, GST_THREAD_STATE_WAITING);
 
+  /* signals the startup of the thread */
+  GST_LOG_OBJECT (element, "signal");
   g_cond_signal (thread->cond);
+  GST_LOG_OBJECT (element, "unlocking lock");
+
+  /* as long as we're not dying we can continue */
   while (!(GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING))) {
+    /* in the playing state we need to do something special */
     if (GST_STATE (thread) == GST_STATE_PLAYING) {
-      GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
-      status = TRUE;
       GST_LOG_OBJECT (thread, "starting to iterate");
-      while (status && GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) {
+      /* continue iteration while spinning */
+      while (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) {
+        gboolean status;
+
         g_mutex_unlock (thread->lock);
         status = gst_bin_iterate (GST_BIN (thread));
-        if (!status)
+        g_mutex_lock (thread->lock);
+
+        if (!status) {
           GST_DEBUG_OBJECT (thread, "iterate returned false");
-        if (GST_FLAG_IS_SET (thread, GST_THREAD_MUTEX_LOCKED)) {
-          GST_FLAG_UNSET (thread, GST_THREAD_MUTEX_LOCKED);
-        } else {
-          g_mutex_lock (thread->lock);
+          if (GST_STATE (thread) != GST_STATE_PLAYING) {
+            GST_DEBUG_OBJECT (thread,
+                "stopping spinning as state is not playing");
+            GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
+          }
         }
       }
-      GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
     }
-    if (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING))
-      break;
-    GST_LOG_OBJECT (thread, "we're caught");
+    /* sync section */
+    GST_LOG_OBJECT (thread, "entering sync");
+    GST_DEBUG_OBJECT (thread, "signal");
     g_cond_signal (thread->cond);
+    GST_DEBUG_OBJECT (thread, "wait");
+    GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
+    GST_FLAG_SET (thread, GST_THREAD_STATE_WAITING);
     g_cond_wait (thread->cond, thread->lock);
+    GST_FLAG_UNSET (thread, GST_THREAD_STATE_WAITING);
+    GST_LOG_OBJECT (thread, "wait done");
   }
+  GST_LOG_OBJECT (thread, "unlocking lock");
+  g_mutex_unlock (thread->lock);
 
   /* we need to destroy the scheduler here because it has mapped it's
    * stack into the threads stack space */
@@ -614,14 +695,11 @@ gst_thread_main_loop (void *arg)
   if (sched)
     gst_scheduler_reset (sched);
 
-  /* must do that before releasing the lock - we might get disposed before being done */
   g_signal_emit (G_OBJECT (thread), gst_thread_signals[SHUTDOWN], 0);
 
-  /* unlock and signal - we are out */
-
+  /* signal - we are out */
   GST_LOG_OBJECT (thread, "Thread %p exits main loop", g_thread_self ());
   g_cond_signal (thread->cond);
-  g_mutex_unlock (thread->lock);
   /* don't assume the GstThread object exists anymore now */
 
   return NULL;
index 62142bc..ce1eb90 100644 (file)
@@ -36,9 +36,7 @@ extern GPrivate *gst_thread_current;
 typedef enum {
   GST_THREAD_STATE_SPINNING    = GST_BIN_FLAG_LAST,
   GST_THREAD_STATE_REAPING,
-  /* when iterating with mutex locked (special cases)
-     may only be set by thread itself */
-  GST_THREAD_MUTEX_LOCKED,
+  GST_THREAD_STATE_WAITING,
 
   /* padding */
   GST_THREAD_FLAG_LAST                 = GST_BIN_FLAG_LAST + 4
index 1d0c260..1b3676f 100644 (file)
@@ -1,9 +1,9 @@
 include ../Rules
 
-tests_pass = thread1 thread2 thread3 thread4 threadf
-tests_fail = thread5 threadd threadg
+tests_pass = thread1 thread2 thread3 thread4 thread5 threadb threadd threade threadf threadg
+tests_fail = threadh
 
-tests_ignore = queue threade threadb threadc
+tests_ignore = queue threadc staticrec
 
 thread1_SOURCES = thread.c
 thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
index 242c617..a7048d4 100644 (file)
@@ -8,7 +8,7 @@
  * by first setting the output thread to play, then the whole pipeline
  */
 
-static gint handoff_count = 0;
+static volatile gint handoff_count = 0;
 
 /* handoff callback */
 static void
index 3a1324e..40eac8d 100644 (file)
@@ -35,11 +35,12 @@ construct_pipeline (GstElement * pipeline)
   gst_bin_add_many (GST_BIN (thread), identity, sink, NULL);
 
   g_object_set (G_OBJECT (src), "num_buffers", 5, NULL);
-  g_object_set (sink, "signal-handoffs", TRUE, NULL);
+  //g_object_set (sink, "signal-handoffs", TRUE, NULL);
 }
 
 void
-change_state (GstElement * element, GstBuffer * buf, GstElement * pipeline)
+change_state (GstElement * element, GstBuffer * buf, GstPad * pad,
+    GstElement * pipeline)
 {
   gst_element_set_state (pipeline, GST_STATE_NULL);
 }
@@ -87,6 +88,7 @@ main (gint argc, gchar * argv[])
     gst_element_set_state (pipeline, GST_STATE_PLAYING);
     g_print ("running ...\n");
     while (gst_bin_iterate (GST_BIN (pipeline)));
+    g_print ("done ...\n");
     gst_element_set_state (pipeline, GST_STATE_NULL);
   }
   if (TESTNUM == 3) {
@@ -117,6 +119,7 @@ main (gint argc, gchar * argv[])
     gst_element_set_state (pipeline, GST_STATE_PLAYING);
     g_print ("running ...\n");
     while (gst_bin_iterate (GST_BIN (pipeline)));
+    g_print ("stopping ...\n");
     gst_element_set_state (pipeline, GST_STATE_NULL);
   }
 
index b5eac46..7f9955c 100644 (file)
@@ -32,7 +32,7 @@ construct_pipeline (GstElement * pipeline, gint identities)
   }
   gst_element_link (identity, sink);
 
-  g_object_set (G_OBJECT (src), "num_buffers", 1, "sizetype", 3, NULL);
+  g_object_set (G_OBJECT (src), "num_buffers", 10, "sizetype", 3, NULL);
 }
 
 void
index 84f66d1..79bfb57 100644 (file)
@@ -8,8 +8,10 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+
+/* must be volatile, we're going to fool the compiler */
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)
@@ -59,8 +61,6 @@ main (gint argc, gchar * argv[])
   gulong id;
   GstElement *thread;
 
-  alarm (10);
-
   gst_init (&argc, &argv);
 
   for (i = 0; i < runs; ++i) {
index 8f11763..fbdb530 100644 (file)
@@ -8,8 +8,8 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)
@@ -55,8 +55,6 @@ main (gint argc, gchar * argv[])
   int i;
   GstElement *pipeline;
 
-  alarm (10);
-
   g_thread_init (NULL);
   gst_init (&argc, &argv);
 
index f04f76d..fd5eeb4 100644 (file)
@@ -10,8 +10,8 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)
index 1d0c260..1b3676f 100644 (file)
@@ -1,9 +1,9 @@
 include ../Rules
 
-tests_pass = thread1 thread2 thread3 thread4 threadf
-tests_fail = thread5 threadd threadg
+tests_pass = thread1 thread2 thread3 thread4 thread5 threadb threadd threade threadf threadg
+tests_fail = threadh
 
-tests_ignore = queue threade threadb threadc
+tests_ignore = queue threadc staticrec
 
 thread1_SOURCES = thread.c
 thread1_CFLAGS = -DTESTNUM=1 $(AM_CFLAGS)
index 242c617..a7048d4 100644 (file)
@@ -8,7 +8,7 @@
  * by first setting the output thread to play, then the whole pipeline
  */
 
-static gint handoff_count = 0;
+static volatile gint handoff_count = 0;
 
 /* handoff callback */
 static void
index 3a1324e..40eac8d 100644 (file)
@@ -35,11 +35,12 @@ construct_pipeline (GstElement * pipeline)
   gst_bin_add_many (GST_BIN (thread), identity, sink, NULL);
 
   g_object_set (G_OBJECT (src), "num_buffers", 5, NULL);
-  g_object_set (sink, "signal-handoffs", TRUE, NULL);
+  //g_object_set (sink, "signal-handoffs", TRUE, NULL);
 }
 
 void
-change_state (GstElement * element, GstBuffer * buf, GstElement * pipeline)
+change_state (GstElement * element, GstBuffer * buf, GstPad * pad,
+    GstElement * pipeline)
 {
   gst_element_set_state (pipeline, GST_STATE_NULL);
 }
@@ -87,6 +88,7 @@ main (gint argc, gchar * argv[])
     gst_element_set_state (pipeline, GST_STATE_PLAYING);
     g_print ("running ...\n");
     while (gst_bin_iterate (GST_BIN (pipeline)));
+    g_print ("done ...\n");
     gst_element_set_state (pipeline, GST_STATE_NULL);
   }
   if (TESTNUM == 3) {
@@ -117,6 +119,7 @@ main (gint argc, gchar * argv[])
     gst_element_set_state (pipeline, GST_STATE_PLAYING);
     g_print ("running ...\n");
     while (gst_bin_iterate (GST_BIN (pipeline)));
+    g_print ("stopping ...\n");
     gst_element_set_state (pipeline, GST_STATE_NULL);
   }
 
index b5eac46..7f9955c 100644 (file)
@@ -32,7 +32,7 @@ construct_pipeline (GstElement * pipeline, gint identities)
   }
   gst_element_link (identity, sink);
 
-  g_object_set (G_OBJECT (src), "num_buffers", 1, "sizetype", 3, NULL);
+  g_object_set (G_OBJECT (src), "num_buffers", 10, "sizetype", 3, NULL);
 }
 
 void
index 84f66d1..79bfb57 100644 (file)
@@ -8,8 +8,10 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+
+/* must be volatile, we're going to fool the compiler */
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)
@@ -59,8 +61,6 @@ main (gint argc, gchar * argv[])
   gulong id;
   GstElement *thread;
 
-  alarm (10);
-
   gst_init (&argc, &argv);
 
   for (i = 0; i < runs; ++i) {
index 8f11763..fbdb530 100644 (file)
@@ -8,8 +8,8 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)
@@ -55,8 +55,6 @@ main (gint argc, gchar * argv[])
   int i;
   GstElement *pipeline;
 
-  alarm (10);
-
   g_thread_init (NULL);
   gst_init (&argc, &argv);
 
index f04f76d..fd5eeb4 100644 (file)
@@ -10,8 +10,8 @@
 #define MAX_IDENTITIES 29
 #define RUNS_PER_IDENTITY 5
 
-gboolean running = FALSE;
-gboolean done = FALSE;
+volatile gboolean running = FALSE;
+volatile gboolean done = FALSE;
 
 static void
 construct_pipeline (GstElement * pipeline, gint identities)