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.
This commit is contained in:
Wim Taymans 2001-12-19 19:22:53 +00:00
parent 23eb626391
commit 5ad018148c
9 changed files with 126 additions and 42 deletions

View 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);
}

View 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);

View 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
@ -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;
}

View 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_object_ref (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
gst_object_sink (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
GST_ELEMENT_SCHED (pipeline) = scheduler;
GST_DEBUG (GST_CAT_PIPELINE, "pipeline's scheduler is %p\n", GST_ELEMENT_SCHED (pipeline));
gst_object_ref (GST_OBJECT (scheduler));
gst_object_sink (GST_OBJECT (scheduler));
gst_scheduler_setup (scheduler);
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)));
}

View file

@ -67,6 +67,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

View 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);

View 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);

View 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;
@ -784,6 +779,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)
{
@ -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);