mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-02 05:28:48 +00:00
task: Introduce gst_task_resume() API
This new API allow resuming a task if it was paused, while leaving it to stopped stated if it was stopped or not started yet. This new API can be useful for callback driver workflow, where you basically want to pause and resume the task when buffers are notified while avoiding the race with a gst_task_stop() coming from another thread.
This commit is contained in:
parent
c682579c5e
commit
e272ae281f
3 changed files with 104 additions and 23 deletions
|
@ -657,33 +657,14 @@ start_task (GstTask * task)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_task_set_state:
|
||||
* @task: a #GstTask
|
||||
* @state: the new task state
|
||||
*
|
||||
* Sets the state of @task to @state.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Returns: %TRUE if the state could be changed.
|
||||
*/
|
||||
gboolean
|
||||
gst_task_set_state (GstTask * task, GstTaskState state)
|
||||
static inline gboolean
|
||||
gst_task_set_state_unlocked (GstTask * task, GstTaskState state)
|
||||
{
|
||||
GstTaskState old;
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TASK (task), FALSE);
|
||||
|
||||
GST_DEBUG_OBJECT (task, "Changing task %p to state %d", task, state);
|
||||
|
||||
GST_OBJECT_LOCK (task);
|
||||
if (state != GST_TASK_STOPPED)
|
||||
if (G_UNLIKELY (GST_TASK_GET_LOCK (task) == NULL))
|
||||
goto no_lock;
|
||||
|
@ -709,7 +690,6 @@ gst_task_set_state (GstTask * task, GstTaskState state)
|
|||
break;
|
||||
}
|
||||
}
|
||||
GST_OBJECT_UNLOCK (task);
|
||||
|
||||
return res;
|
||||
|
||||
|
@ -717,12 +697,41 @@ gst_task_set_state (GstTask * task, GstTaskState state)
|
|||
no_lock:
|
||||
{
|
||||
GST_WARNING_OBJECT (task, "state %d set on task without a lock", state);
|
||||
GST_OBJECT_UNLOCK (task);
|
||||
g_warning ("task without a lock can't be set to state %d", state);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_task_set_state:
|
||||
* @task: a #GstTask
|
||||
* @state: the new task state
|
||||
*
|
||||
* Sets the state of @task to @state.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* MT safe.
|
||||
*
|
||||
* Returns: %TRUE if the state could be changed.
|
||||
*/
|
||||
gboolean
|
||||
gst_task_set_state (GstTask * task, GstTaskState state)
|
||||
{
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TASK (task), FALSE);
|
||||
|
||||
GST_OBJECT_LOCK (task);
|
||||
res = gst_task_set_state_unlocked (task, state);
|
||||
GST_OBJECT_UNLOCK (task);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_task_start:
|
||||
* @task: The #GstTask to start
|
||||
|
@ -777,6 +786,32 @@ gst_task_pause (GstTask * task)
|
|||
return gst_task_set_state (task, GST_TASK_PAUSED);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_task_resume:
|
||||
* @task: The #GstTask to resume
|
||||
*
|
||||
* Resume @task in case it was paused. If the task was stopped, it will
|
||||
* remain in that state and this function will return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE if the task could be resumed.
|
||||
*
|
||||
* MT safe.
|
||||
* Since: 1.18
|
||||
*/
|
||||
gboolean
|
||||
gst_task_resume (GstTask * task)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
g_return_val_if_fail (GST_IS_TASK (task), FALSE);
|
||||
|
||||
GST_OBJECT_LOCK (task);
|
||||
if (GET_TASK_STATE (task) != GST_TASK_STOPPED)
|
||||
res = gst_task_set_state_unlocked (task, GST_TASK_STARTED);
|
||||
GST_OBJECT_UNLOCK (task);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_task_join:
|
||||
* @task: The #GstTask to join
|
||||
|
|
|
@ -207,6 +207,9 @@ gboolean gst_task_stop (GstTask *task);
|
|||
GST_API
|
||||
gboolean gst_task_pause (GstTask *task);
|
||||
|
||||
GST_API
|
||||
gboolean gst_task_resume (GstTask *task);
|
||||
|
||||
GST_API
|
||||
gboolean gst_task_join (GstTask *task);
|
||||
|
||||
|
|
|
@ -31,6 +31,48 @@ static GRecMutex task_mutex;
|
|||
|
||||
#define TEST_RACE_ITERATIONS 1000
|
||||
|
||||
static void
|
||||
task_resume_func (void *data)
|
||||
{
|
||||
g_mutex_lock (&task_lock);
|
||||
g_cond_signal (&task_cond);
|
||||
g_mutex_unlock (&task_lock);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_resume)
|
||||
{
|
||||
GstTask *t;
|
||||
|
||||
t = gst_task_new (task_resume_func, &t, NULL);
|
||||
fail_if (t == NULL);
|
||||
|
||||
g_rec_mutex_init (&task_mutex);
|
||||
gst_task_set_lock (t, &task_mutex);
|
||||
|
||||
g_cond_init (&task_cond);
|
||||
g_mutex_init (&task_lock);
|
||||
|
||||
g_mutex_lock (&task_lock);
|
||||
|
||||
/* Pause the task, and resume it. */
|
||||
fail_unless (gst_task_pause (t));
|
||||
fail_unless (gst_task_resume (t));
|
||||
|
||||
while (GST_TASK_STATE (t) != GST_TASK_STARTED)
|
||||
g_cond_wait (&task_cond, &task_lock);
|
||||
|
||||
fail_unless (gst_task_stop (t));
|
||||
g_mutex_unlock (&task_lock);
|
||||
fail_unless (gst_task_join (t));
|
||||
|
||||
/* Make sure we cannot resume from stopped. */
|
||||
fail_if (gst_task_resume (t));
|
||||
|
||||
gst_object_unref (t);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
task_signal_pause_func (void *data)
|
||||
{
|
||||
|
@ -265,6 +307,7 @@ gst_task_suite (void)
|
|||
tcase_add_test (tc_chain, test_lock_start);
|
||||
tcase_add_test (tc_chain, test_join);
|
||||
tcase_add_test (tc_chain, test_pause_stop_race);
|
||||
tcase_add_test (tc_chain, test_resume);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue