From 5ad018148cfac426ea8e5ba19d945c3837081a7c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 19 Dec 2001 19:22:53 +0000 Subject: [PATCH] Some more work on cleanup. 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 | 4 +-- gst/cothreads.c | 6 ++-- gst/gstbin.c | 11 ++++--- gst/gstpad.c | 31 ++++++++++-------- gst/gstpipeline.c | 15 ++++++--- gst/gstscheduler.c | 26 +++++++++++++++ gst/gstscheduler.h | 4 +++ gst/gstthread.c | 5 +++ gst/schedulers/gstbasicscheduler.c | 66 +++++++++++++++++++++++++++++--------- 9 files changed, 126 insertions(+), 42 deletions(-) diff --git a/gst/Makefile.am b/gst/Makefile.am index 4d09d49..b12b325 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -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) diff --git a/gst/cothreads.c b/gst/cothreads.c index 8bb1bc7..db029a3 100644 --- a/gst/cothreads.c +++ b/gst/cothreads.c @@ -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); } diff --git a/gst/gstbin.c b/gst/gstbin.c index d697b47..c1a1b00 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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); diff --git a/gst/gstpad.c b/gst/gstpad.c index 1308b18..113f190 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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; } diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 0a70f22..dd1b459 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -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))); } diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c index 6284ac1..553c520 100644 --- a/gst/gstscheduler.c +++ b/gst/gstscheduler.c @@ -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 diff --git a/gst/gstscheduler.h b/gst/gstscheduler.h index e9a5f35..c60b55c 100644 --- a/gst/gstscheduler.h +++ b/gst/gstscheduler.h @@ -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); diff --git a/gst/gstthread.c b/gst/gstthread.c index 8c91a63..a11bcfe 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -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); diff --git a/gst/schedulers/gstbasicscheduler.c b/gst/schedulers/gstbasicscheduler.c index c31bc92..f465859 100644 --- a/gst/schedulers/gstbasicscheduler.c +++ b/gst/schedulers/gstbasicscheduler.c @@ -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); -- 2.7.4