From c31c3f215fd18eda71bdbf0111878e147aae4339 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 11 May 2009 22:59:35 +0200 Subject: [PATCH] GstTask: unify task state functions Add new gst_task_set_state() to change the state of the task instead of duplicating the code in each function. API: GstTask::gst_task_set_state() --- docs/gst/gstreamer-sections.txt | 1 + gst/gsttask.c | 198 ++++++++++++++++++---------------------- gst/gsttask.h | 1 + win32/common/libgstreamer.def | 1 + 4 files changed, 91 insertions(+), 110 deletions(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 789ef4f..afad541 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -2176,6 +2176,7 @@ GST_TASK_WAIT gst_task_cleanup_all gst_task_create gst_task_get_state +gst_task_set_state gst_task_join gst_task_pause gst_task_set_lock diff --git a/gst/gsttask.c b/gst/gsttask.c index 0f88dfe..43069b6 100644 --- a/gst/gsttask.c +++ b/gst/gsttask.c @@ -320,79 +320,123 @@ gst_task_get_state (GstTask * task) return result; } +/* make sure the task is running and start a thread if it's not. + * This function must be called with the task LOCK. */ +static gboolean +start_task (GstTask * task) +{ + gboolean res = TRUE; + GstTaskClass *tclass; + GError *error = NULL; + + /* new task, We ref before so that it remains alive while + * the thread is running. */ + gst_object_ref (task); + /* mark task as running so that a join will wait until we schedule + * and exit the task function. */ + task->running = TRUE; + + tclass = GST_TASK_GET_CLASS (task); + + /* push on the thread pool */ + g_static_mutex_lock (&pool_lock); + g_thread_pool_push (tclass->pool, task, &error); + g_static_mutex_unlock (&pool_lock); + + if (error != NULL) { + g_warning ("failed to create thread: %s", error->message); + g_error_free (error); + res = FALSE; + } + return res; +} + + /** - * gst_task_start: - * @task: The #GstTask to start + * gst_task_set_state: + * @task: a #GstTask + * @state: the new task state * - * Starts @task. The @task must have a lock associated with it using - * gst_task_set_lock() or this function will return %FALSE. + * Sets the state of @task to @state. * - * Returns: %TRUE if the task could be started. + * The @task must have a lock associated with it using + * gst_task_set_lock() when going to GST_TASK_STARTED or GST_TASK_PAUSED or + * this function will return %FALSE. + * + * Returns: %TRUE if the state could be changed. + * + * Since: 0.10.24 * * MT safe. */ gboolean -gst_task_start (GstTask * task) +gst_task_set_state (GstTask * task, GstTaskState state) { GstTaskState old; + gboolean res = TRUE; g_return_val_if_fail (GST_IS_TASK (task), FALSE); - GST_DEBUG_OBJECT (task, "Starting task %p", task); + GST_DEBUG_OBJECT (task, "Changing task %p to state %d", task, state); GST_OBJECT_LOCK (task); - if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL)) - goto no_lock; + if (state != GST_TASK_STOPPED) + if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL)) + goto no_lock; + /* if the state changed, do our thing */ old = task->state; - task->state = GST_TASK_STARTED; - switch (old) { - case GST_TASK_STOPPED: - { - GstTaskClass *tclass; - - /* If the task already has a thread scheduled we don't have to do - * anything. */ - if (task->running) + if (old != state) { + task->state = state; + switch (old) { + case GST_TASK_STOPPED: + /* If the task already has a thread scheduled we don't have to do + * anything. */ + if (G_UNLIKELY (!task->running)) + res = start_task (task); + break; + case GST_TASK_PAUSED: + /* when we are paused, signal to go to the new state */ + GST_TASK_SIGNAL (task); + break; + case GST_TASK_STARTED: + /* if we were started, we'll go to the new state after the next + * iteration. */ break; - - /* new task, push on thread pool. We ref before so - * that it remains alive while on the thread pool. */ - gst_object_ref (task); - /* mark task as running so that a join will wait until we schedule - * and exit the task function. */ - task->running = TRUE; - - tclass = GST_TASK_GET_CLASS (task); - - g_static_mutex_lock (&pool_lock); - g_thread_pool_push (tclass->pool, task, NULL); - g_static_mutex_unlock (&pool_lock); - break; } - case GST_TASK_PAUSED: - /* PAUSE to PLAY, signal */ - GST_TASK_SIGNAL (task); - break; - case GST_TASK_STARTED: - /* was OK */ - break; } GST_OBJECT_UNLOCK (task); - return TRUE; + return res; /* ERRORS */ no_lock: { - GST_WARNING_OBJECT (task, "starting task without a lock"); + GST_WARNING_OBJECT (task, "state %d set on task without a lock", state); GST_OBJECT_UNLOCK (task); - g_warning ("starting task without a lock"); + g_warning ("task without a lock can't be set to state %d", state); return FALSE; } } /** + * gst_task_start: + * @task: The #GstTask to start + * + * Starts @task. The @task must have a lock associated with it using + * gst_task_set_lock() or this function will return %FALSE. + * + * Returns: %TRUE if the task could be started. + * + * MT safe. + */ +gboolean +gst_task_start (GstTask * task) +{ + return gst_task_set_state (task, GST_TASK_STARTED); +} + +/** * gst_task_stop: * @task: The #GstTask to stop * @@ -407,27 +451,7 @@ no_lock: gboolean gst_task_stop (GstTask * task) { - GstTaskState old; - - g_return_val_if_fail (GST_IS_TASK (task), FALSE); - - GST_DEBUG_OBJECT (task, "Stopping task %p", task); - - GST_OBJECT_LOCK (task); - old = task->state; - task->state = GST_TASK_STOPPED; - switch (old) { - case GST_TASK_STOPPED: - break; - case GST_TASK_PAUSED: - GST_TASK_SIGNAL (task); - break; - case GST_TASK_STARTED: - break; - } - GST_OBJECT_UNLOCK (task); - - return TRUE; + return gst_task_set_state (task, GST_TASK_STOPPED); } /** @@ -446,53 +470,7 @@ gst_task_stop (GstTask * task) gboolean gst_task_pause (GstTask * task) { - GstTaskState old; - - g_return_val_if_fail (GST_IS_TASK (task), FALSE); - - GST_DEBUG_OBJECT (task, "Pausing task %p", task); - - GST_OBJECT_LOCK (task); - if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL)) - goto no_lock; - - old = task->state; - task->state = GST_TASK_PAUSED; - switch (old) { - case GST_TASK_STOPPED: - { - GstTaskClass *tclass; - - if (task->running) - break; - - gst_object_ref (task); - task->running = TRUE; - - tclass = GST_TASK_GET_CLASS (task); - - g_static_mutex_lock (&pool_lock); - g_thread_pool_push (tclass->pool, task, NULL); - g_static_mutex_unlock (&pool_lock); - break; - } - case GST_TASK_PAUSED: - break; - case GST_TASK_STARTED: - break; - } - GST_OBJECT_UNLOCK (task); - - return TRUE; - - /* ERRORS */ -no_lock: - { - GST_WARNING_OBJECT (task, "pausing task without a lock"); - GST_OBJECT_UNLOCK (task); - g_warning ("pausing task without a lock"); - return FALSE; - } + return gst_task_set_state (task, GST_TASK_PAUSED); } /** diff --git a/gst/gsttask.h b/gst/gsttask.h index 70c4ab4..65a9bf8 100644 --- a/gst/gsttask.h +++ b/gst/gsttask.h @@ -162,6 +162,7 @@ GstTask* gst_task_create (GstTaskFunction func, gpointer data); void gst_task_set_lock (GstTask *task, GStaticRecMutex *mutex); GstTaskState gst_task_get_state (GstTask *task); +gboolean gst_task_set_state (GstTask *task, GstTaskState state); gboolean gst_task_start (GstTask *task); gboolean gst_task_stop (GstTask *task); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 339f2e6..50fecfe 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -939,6 +939,7 @@ EXPORTS gst_task_join gst_task_pause gst_task_set_lock + gst_task_set_state gst_task_start gst_task_state_get_type gst_task_stop -- 2.7.4