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) { if (ctx->threads[i]->lock) {
g_mutex_unlock(ctx->threads[i]->lock); g_mutex_unlock(ctx->threads[i]->lock);
g_mutex_free (ctx->threads[i]->lock); g_mutex_free (ctx->threads[i]->lock);
ctx->threads[i]->lock = NULL;
} }
#endif #endif
if (i == 0) if (i == 0) {
g_free (ctx->threads[i]); g_free (ctx->threads[i]);
ctx->threads[i] = NULL;
}
} }
g_hash_table_destroy (ctx->data); g_hash_table_destroy (ctx->data);
g_free (ctx); 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 (element != NULL);
g_return_if_fail (GST_IS_ELEMENT (element)); 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_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from it sched %p",
GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element)); GST_ELEMENT_NAME (element), GST_ELEMENT_SCHED (element));
@ -335,11 +341,6 @@ gst_bin_remove (GstBin * bin, GstElement * element)
GST_ELEMENT_NAME (bin)); GST_ELEMENT_NAME (bin));
return; 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 */ /* remove this element from the list of managed elements */
gst_bin_unset_element_sched (element); 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(realsrc) = NULL;
GST_RPAD_PEER(realsink) = NULL; GST_RPAD_PEER(realsink) = NULL;
// now tell the scheduler /* now tell the scheduler */
if (realsrc->sched) if (GST_PAD_PARENT (realsrc)->sched)
gst_scheduler_pad_disconnect (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); 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 */ /* 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); 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); return GST_PAD_PADTEMPLATE (pad);
} }
/**
/*
* gst_pad_set_sched: * gst_pad_set_sched:
* @pad: the pad to set the scheduler for * @pad: the pad to set the scheduler for
* @sched: The scheduler to set * @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))); 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 */ /* FIXME we should destroy the ghostpads, because they are nothing without the real pad */
if (GST_REAL_PAD (pad)->ghostpads) { if (GST_REAL_PAD (pad)->ghostpads) {
GList *orig, *ghostpads; GList *orig, *ghostpads;
@ -1052,7 +1050,7 @@ gst_real_pad_dispose (GObject *object)
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))){ 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_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); ghostpads = g_list_next (ghostpads);
} }
@ -1060,6 +1058,11 @@ gst_real_pad_dispose (GObject *object)
g_list_free (GST_REAL_PAD(pad)->ghostpads); 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); G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
} }
@ -1579,7 +1582,7 @@ gst_pad_select (GList *padlist)
{ {
GstPad *pad; 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; return pad;
} }

View file

@ -97,15 +97,21 @@ gst_pipeline_class_init (GstPipelineClass *klass)
static void static void
gst_pipeline_init (GstPipeline *pipeline) gst_pipeline_init (GstPipeline *pipeline)
{ {
GstScheduler *scheduler;
/* we're a manager by default */ /* we're a manager by default */
GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER); 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_ELEMENT_SCHED (pipeline) = scheduler;
gst_object_sink (GST_OBJECT (GST_ELEMENT_SCHED (pipeline)));
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 static void
@ -115,6 +121,7 @@ gst_pipeline_dispose (GObject *object)
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
gst_scheduler_reset (GST_ELEMENT_SCHED (pipeline));
gst_object_unref (GST_OBJECT (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: * gst_scheduler_pad_connect:
* @sched: the schedulerr * @sched: the schedulerr

View file

@ -65,6 +65,8 @@ struct _GstScheduler {
struct _GstSchedulerClass { struct _GstSchedulerClass {
GstObjectClass parent_class; GstObjectClass parent_class;
void (*setup) (GstScheduler *sched);
void (*reset) (GstScheduler *sched);
void (*add_element) (GstScheduler *sched, GstElement *element); void (*add_element) (GstScheduler *sched, GstElement *element);
void (*remove_element) (GstScheduler *sched, GstElement *element); void (*remove_element) (GstScheduler *sched, GstElement *element);
void (*enable_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)) #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_add_element (GstScheduler *sched, GstElement *element);
void gst_scheduler_remove_element (GstScheduler *sched, GstElement *element); void gst_scheduler_remove_element (GstScheduler *sched, GstElement *element);
void gst_scheduler_enable_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); g_mutex_lock (thread->lock);
gst_scheduler_setup (GST_ELEMENT_SCHED (thread));
GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING); GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
thread->pid = getpid(); thread->pid = getpid();
@ -549,6 +550,10 @@ gst_thread_main_loop (void *arg)
break; 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 */ /* since we don't unlock at the end of the while loop, do it here */
g_mutex_unlock (thread->lock); 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_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_add_element (GstScheduler *sched, GstElement *element);
static void gst_basic_scheduler_remove_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); 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); 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->add_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_add_element);
klass->remove_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_remove_element); klass->remove_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_remove_element);
klass->enable_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_enable_element); klass->enable_element = GST_DEBUG_FUNCPTR (gst_basic_scheduler_enable_element);
@ -116,12 +120,6 @@ gst_basic_scheduler_init (GstScheduler *scheduler)
static void static void
gst_basic_scheduler_dispose (GObject *object) 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); 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"); GST_DEBUG (GST_CAT_SCHEDULING, "chain is using COTHREADS\n");
/* first create thread context */ g_assert (bin->threadcontext != NULL);
if (bin->threadcontext == NULL) {
GST_DEBUG (GST_CAT_SCHEDULING, "initializing cothread context\n");
bin->threadcontext = cothread_init ();
}
/* walk through all the chain's elements */ /* walk through all the chain's elements */
elements = chain->elements; elements = chain->elements;
@ -784,6 +779,37 @@ gst_basic_scheduler_chain_recursive_add (GstSchedulerChain * chain, GstElement *
/* /*
* Entry points for this scheduler. * 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 static void
gst_basic_scheduler_add_element (GstScheduler * sched, GstElement * element) 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 * since they are guaranteed to be in the same chain
* FIXME is it potentially better to make an attempt at splitting cleaner?? * FIXME is it potentially better to make an attempt at splitting cleaner??
*/ */
chain = gst_basic_scheduler_find_chain (sched, element1); chain1 = gst_basic_scheduler_find_chain (sched, element1);
if (chain) { 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_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 */ /* now create a new chain to hold element1 and build it from scratch */
chain1 = gst_basic_scheduler_chain_new (sched); 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 */ /* 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 */ /* if not in chain, create chain and build from scratch */
chain2 = gst_basic_scheduler_chain_new (sched); chain2 = gst_basic_scheduler_chain_new (sched);
gst_basic_scheduler_chain_recursive_add (chain2, element2); gst_basic_scheduler_chain_recursive_add (chain2, element2);