From: Wim Taymans Date: Mon, 6 Sep 2004 15:57:11 +0000 (+0000) Subject: Reworked the GstThread implementation, make more operations threadsafe and more reliable. X-Git-Tag: RELEASE-0_8_6~26 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5905655eadeca3e90e15fc64fdc17c737e1af3ab;p=platform%2Fupstream%2Fgstreamer.git Reworked the GstThread implementation, make more operations threadsafe and more reliable. 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. --- diff --git a/gst/gstthread.c b/gst/gstthread.c index bc7b1f7..3f07c5b 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -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; diff --git a/gst/gstthread.h b/gst/gstthread.h index 62142bc..ce1eb90 100644 --- a/gst/gstthread.h +++ b/gst/gstthread.h @@ -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 diff --git a/tests/old/testsuite/threads/Makefile.am b/tests/old/testsuite/threads/Makefile.am index 1d0c260..1b3676f 100644 --- a/tests/old/testsuite/threads/Makefile.am +++ b/tests/old/testsuite/threads/Makefile.am @@ -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) diff --git a/tests/old/testsuite/threads/queue.c b/tests/old/testsuite/threads/queue.c index 242c617..a7048d4 100644 --- a/tests/old/testsuite/threads/queue.c +++ b/tests/old/testsuite/threads/queue.c @@ -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 diff --git a/tests/old/testsuite/threads/thread.c b/tests/old/testsuite/threads/thread.c index 3a1324e..40eac8d 100644 --- a/tests/old/testsuite/threads/thread.c +++ b/tests/old/testsuite/threads/thread.c @@ -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); } diff --git a/tests/old/testsuite/threads/threadc.c b/tests/old/testsuite/threads/threadc.c index b5eac46..7f9955c 100644 --- a/tests/old/testsuite/threads/threadc.c +++ b/tests/old/testsuite/threads/threadc.c @@ -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 diff --git a/tests/old/testsuite/threads/threadd.c b/tests/old/testsuite/threads/threadd.c index 84f66d1..79bfb57 100644 --- a/tests/old/testsuite/threads/threadd.c +++ b/tests/old/testsuite/threads/threadd.c @@ -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) { diff --git a/tests/old/testsuite/threads/threade.c b/tests/old/testsuite/threads/threade.c index 8f11763..fbdb530 100644 --- a/tests/old/testsuite/threads/threade.c +++ b/tests/old/testsuite/threads/threade.c @@ -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); diff --git a/tests/old/testsuite/threads/threadf.c b/tests/old/testsuite/threads/threadf.c index f04f76d..fd5eeb4 100644 --- a/tests/old/testsuite/threads/threadf.c +++ b/tests/old/testsuite/threads/threadf.c @@ -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) diff --git a/testsuite/threads/Makefile.am b/testsuite/threads/Makefile.am index 1d0c260..1b3676f 100644 --- a/testsuite/threads/Makefile.am +++ b/testsuite/threads/Makefile.am @@ -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) diff --git a/testsuite/threads/queue.c b/testsuite/threads/queue.c index 242c617..a7048d4 100644 --- a/testsuite/threads/queue.c +++ b/testsuite/threads/queue.c @@ -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 diff --git a/testsuite/threads/thread.c b/testsuite/threads/thread.c index 3a1324e..40eac8d 100644 --- a/testsuite/threads/thread.c +++ b/testsuite/threads/thread.c @@ -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); } diff --git a/testsuite/threads/threadc.c b/testsuite/threads/threadc.c index b5eac46..7f9955c 100644 --- a/testsuite/threads/threadc.c +++ b/testsuite/threads/threadc.c @@ -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 diff --git a/testsuite/threads/threadd.c b/testsuite/threads/threadd.c index 84f66d1..79bfb57 100644 --- a/testsuite/threads/threadd.c +++ b/testsuite/threads/threadd.c @@ -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) { diff --git a/testsuite/threads/threade.c b/testsuite/threads/threade.c index 8f11763..fbdb530 100644 --- a/testsuite/threads/threade.c +++ b/testsuite/threads/threade.c @@ -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); diff --git a/testsuite/threads/threadf.c b/testsuite/threads/threadf.c index f04f76d..fd5eeb4 100644 --- a/testsuite/threads/threadf.c +++ b/testsuite/threads/threadf.c @@ -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)