task: add separate methods to add enter/leave callback

Remove the structure of callbacks and replace with separate methods to register
each callback. This is much more binding friendly.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=677898
This commit is contained in:
Wim Taymans 2012-06-20 11:59:09 +02:00
parent 76e8b2ecda
commit b2aa56f4e3
4 changed files with 94 additions and 69 deletions

View file

@ -54,6 +54,10 @@ gst_atomic_queue_peek
gst_atomic_queue_pop
gst_atomic_queue_length
<SUBSECTION Standard>
GST_TYPE_ATOMIC_QUEUE
gst_atomic_queue_get_type
</SECTION>
<SECTION>
@ -582,6 +586,7 @@ gst_element_factory_get_klass
gst_element_factory_get_longname
gst_pad_get_caps_reffed
gst_pad_peer_get_caps_reffed
gst_pad_set_caps
gst_buffer_new_and_alloc
GST_BUFFER_TIMESTAMP
GST_BUFFER_TIMESTAMP_IS_VALID
@ -2672,8 +2677,9 @@ gst_task_set_lock
gst_task_set_pool
gst_task_get_pool
GstTaskThreadCallbacks
gst_task_set_thread_callbacks
GstTaskThreadFunc
gst_task_set_enter_callback
gst_task_set_leave_callback
gst_task_get_state
gst_task_set_state

View file

@ -5070,11 +5070,6 @@ pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data)
thread, task);
}
static GstTaskThreadCallbacks thr_callbacks = {
pad_enter_thread,
pad_leave_thread,
};
/**
* gst_pad_start_task:
* @pad: the #GstPad to start the task of
@ -5106,7 +5101,8 @@ gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer user_data,
if (task == NULL) {
task = gst_task_new (func, user_data, notify);
gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad));
gst_task_set_thread_callbacks (task, &thr_callbacks, pad, NULL);
gst_task_set_enter_callback (task, pad_enter_thread, pad, NULL);
gst_task_set_leave_callback (task, pad_leave_thread, pad, NULL);
GST_INFO_OBJECT (pad, "created task %p", task);
GST_PAD_TASK (pad) = task;
gst_object_ref (task);

View file

@ -92,9 +92,13 @@ GST_DEBUG_CATEGORY_STATIC (task_debug);
struct _GstTaskPrivate
{
/* callbacks for managing the thread of this task */
GstTaskThreadCallbacks thr_callbacks;
gpointer thr_user_data;
GDestroyNotify thr_notify;
GstTaskThreadFunc enter_func;
gpointer enter_user_data;
GDestroyNotify enter_notify;
GstTaskThreadFunc leave_func;
gpointer leave_user_data;
GDestroyNotify leave_notify;
/* configured pool */
GstTaskPool *pool;
@ -203,10 +207,11 @@ gst_task_finalize (GObject * object)
GST_DEBUG ("task %p finalize", task);
if (priv->thr_notify)
priv->thr_notify (priv->thr_user_data);
priv->thr_notify = NULL;
priv->thr_user_data = NULL;
if (priv->enter_notify)
priv->enter_notify (priv->enter_user_data);
if (priv->leave_notify)
priv->leave_notify (priv->leave_user_data);
if (task->notify)
task->notify (task->user_data);
@ -276,9 +281,9 @@ gst_task_func (GstTask * task)
task->thread = tself;
GST_OBJECT_UNLOCK (task);
/* fire the enter_thread callback when we need to */
if (priv->thr_callbacks.enter_thread)
priv->thr_callbacks.enter_thread (task, tself, priv->thr_user_data);
/* fire the enter_func callback when we need to */
if (priv->enter_func)
priv->enter_func (task, tself, priv->enter_user_data);
/* locking order is TASK_LOCK, LOCK */
g_rec_mutex_lock (lock);
@ -317,11 +322,11 @@ done:
task->thread = NULL;
exit:
if (priv->thr_callbacks.leave_thread) {
/* fire the leave_thread callback when we need to. We need to do this before
if (priv->leave_func) {
/* fire the leave_func callback when we need to. We need to do this before
* we signal the task and with the task lock released. */
GST_OBJECT_UNLOCK (task);
priv->thr_callbacks.leave_thread (task, tself, priv->thr_user_data);
priv->leave_func (task, tself, priv->leave_user_data);
GST_OBJECT_LOCK (task);
}
/* now we allow messing with the lock again by setting the running flag to
@ -503,56 +508,79 @@ gst_task_set_pool (GstTask * task, GstTaskPool * pool)
gst_object_unref (old);
}
/**
* gst_task_set_thread_callbacks:
* gst_task_set_enter_callback:
* @task: The #GstTask to use
* @callbacks: (in): a #GstTaskThreadCallbacks pointer
* @user_data: (closure): user data passed to the callbacks
* @enter_func: (in): a #GstTaskThreadFunc
* @user_data: user data passed to @enter_func
* @notify: called when @user_data is no longer referenced
*
* Set callbacks which will be executed when a new thread is needed, the thread
* function is entered and left and when the thread is joined.
*
* By default a thread for @task will be created from a default thread pool.
*
* Objects can use custom GThreads or can perform additional configuration of
* the threads (such as changing the thread priority) by installing callbacks.
*
* MT safe.
*
* Since: 0.10.24
* Call @enter_func when the task function of @task is entered. @user_data will
* be passed to @enter_func and @notify will be called when @user_data is no
* longer referenced.
*/
void
gst_task_set_thread_callbacks (GstTask * task,
GstTaskThreadCallbacks * callbacks, gpointer user_data,
GDestroyNotify notify)
gst_task_set_enter_callback (GstTask * task, GstTaskThreadFunc enter_func,
gpointer user_data, GDestroyNotify notify)
{
GDestroyNotify old_notify;
g_return_if_fail (task != NULL);
g_return_if_fail (GST_IS_TASK (task));
g_return_if_fail (callbacks != NULL);
GST_OBJECT_LOCK (task);
old_notify = task->priv->thr_notify;
if ((old_notify = task->priv->enter_notify)) {
gpointer old_data = task->priv->enter_user_data;
if (old_notify) {
gpointer old_data;
old_data = task->priv->thr_user_data;
task->priv->thr_user_data = NULL;
task->priv->thr_notify = NULL;
task->priv->enter_user_data = NULL;
task->priv->enter_notify = NULL;
GST_OBJECT_UNLOCK (task);
old_notify (old_data);
GST_OBJECT_LOCK (task);
}
task->priv->thr_callbacks = *callbacks;
task->priv->thr_user_data = user_data;
task->priv->thr_notify = notify;
task->priv->enter_func = enter_func;
task->priv->enter_user_data = user_data;
task->priv->enter_notify = notify;
GST_OBJECT_UNLOCK (task);
}
/**
* gst_task_set_leave_callback:
* @task: The #GstTask to use
* @leave_func: (in): a #GstTaskThreadFunc
* @user_data: user data passed to @leave_func
* @notify: called when @user_data is no longer referenced
*
* Call @leave_func when the task function of @task is left. @user_data will
* be passed to @leave_func and @notify will be called when @user_data is no
* longer referenced.
*/
void
gst_task_set_leave_callback (GstTask * task, GstTaskThreadFunc leave_func,
gpointer user_data, GDestroyNotify notify)
{
GDestroyNotify old_notify;
g_return_if_fail (task != NULL);
g_return_if_fail (GST_IS_TASK (task));
GST_OBJECT_LOCK (task);
if ((old_notify = task->priv->leave_notify)) {
gpointer old_data = task->priv->leave_user_data;
task->priv->leave_user_data = NULL;
task->priv->leave_notify = NULL;
GST_OBJECT_UNLOCK (task);
old_notify (old_data);
GST_OBJECT_LOCK (task);
}
task->priv->leave_func = leave_func;
task->priv->leave_user_data = user_data;
task->priv->leave_notify = notify;
GST_OBJECT_UNLOCK (task);
}

View file

@ -110,23 +110,14 @@ typedef enum {
#define GST_TASK_GET_LOCK(task) (GST_TASK_CAST(task)->lock)
/**
* GstTaskThreadCallbacks:
* @enter_thread: a thread is entered, this callback is called when the new
* thread enters its function.
* @leave_thread: a thread is exiting, this is called when the thread is about
* to leave its function
* GstTaskThreadFunc:
* @task: The #GstTask
* @thread: The #GThread
* @user_data: user data
*
* Custom GstTask thread callback functions that can be installed.
*
* Since: 0.10.24
*/
typedef struct {
/* manage the lifetime of the thread */
void (*enter_thread) (GstTask *task, GThread *thread, gpointer user_data);
void (*leave_thread) (GstTask *task, GThread *thread, gpointer user_data);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
} GstTaskThreadCallbacks;
typedef void (*GstTaskThreadFunc) (GstTask *task, GThread *thread, gpointer user_data);
/**
* GstTask:
@ -185,10 +176,14 @@ void gst_task_set_lock (GstTask *task, GRecMutex *mutex);
GstTaskPool * gst_task_get_pool (GstTask *task);
void gst_task_set_pool (GstTask *task, GstTaskPool *pool);
void gst_task_set_thread_callbacks (GstTask *task,
GstTaskThreadCallbacks *callbacks,
gpointer user_data,
GDestroyNotify notify);
void gst_task_set_enter_callback (GstTask *task,
GstTaskThreadFunc enter_func,
gpointer user_data,
GDestroyNotify notify);
void gst_task_set_leave_callback (GstTask *task,
GstTaskThreadFunc leave_func,
gpointer user_data,
GDestroyNotify notify);
GstTaskState gst_task_get_state (GstTask *task);
gboolean gst_task_set_state (GstTask *task, GstTaskState state);