2 * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
4 * threadscheduler.c: scheduler using threads
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "../gst-i18n-lib.h"
29 GST_DEBUG_CATEGORY_STATIC (debug_scheduler);
30 #define GST_CAT_DEFAULT debug_scheduler
32 #define GST_TYPE_THREAD_SCHEDULER \
33 (gst_thread_scheduler_get_type ())
34 #define GST_THREAD_SCHEDULER(obj) \
35 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THREAD_SCHEDULER,GstThreadScheduler))
36 #define GST_THREAD_SCHEDULER_CLASS(klass) \
37 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THREAD_SCHEDULER,GstThreadSchedulerClass))
38 #define GST_IS_THREAD_SCHEDULER(obj) \
39 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THREAD_SCHEDULER))
40 #define GST_IS_THREAD_SCHEDULER_CLASS(obj) \
41 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THREAD_SCHEDULER))
43 #define SCHED(element) (GST_THREAD_SCHEDULER ((element)->sched))
45 GType gst_thread_scheduler_get_type (void);
47 typedef struct _GstThreadScheduler GstThreadScheduler;
48 typedef struct _GstThreadSchedulerClass GstThreadSchedulerClass;
50 struct _GstThreadScheduler
52 GstScheduler scheduler;
57 struct _GstThreadSchedulerClass
59 GstSchedulerClass scheduler_class;
62 #define ELEMENT_PRIVATE(element) GST_ELEMENT (element)->sched_private
63 #define PAD_PRIVATE(pad) (GST_REAL_PAD (pad))->sched_private
65 #define GST_TYPE_THREAD_SCHEDULER_TASK \
66 (gst_thread_scheduler_task_get_type ())
67 #define GST_THREAD_SCHEDULER_TASK(obj) \
68 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THREAD_SCHEDULER_TASK,GstThreadSchedulerTask))
69 #define GST_THREAD_SCHEDULER_TASK_CLASS(klass) \
70 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THREAD_SCHEDULER_TASK,GstThreadSchedulerTaskClass))
71 #define GST_IS_THREAD_SCHEDULER_TASK(obj) \
72 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THREAD_SCHEDULER_TASK))
73 #define GST_IS_THREAD_SCHEDULER_TASK_CLASS(obj) \
74 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THREAD_SCHEDULER_TASK))
76 typedef struct _GstThreadSchedulerTask GstThreadSchedulerTask;
77 typedef struct _GstThreadSchedulerTaskClass GstThreadSchedulerTaskClass;
79 struct _GstThreadSchedulerTask
84 struct _GstThreadSchedulerTaskClass
86 GstTaskClass parent_class;
89 static void gst_thread_scheduler_task_class_init (gpointer g_class,
91 static void gst_thread_scheduler_task_init (GstThreadSchedulerTask * object);
93 static gboolean gst_thread_scheduler_task_start (GstTask * task);
94 static gboolean gst_thread_scheduler_task_stop (GstTask * task);
95 static gboolean gst_thread_scheduler_task_pause (GstTask * task);
98 gst_thread_scheduler_task_get_type (void)
100 static GType object_type = 0;
102 if (object_type == 0) {
103 static const GTypeInfo object_info = {
104 sizeof (GstThreadSchedulerTaskClass),
107 gst_thread_scheduler_task_class_init,
110 sizeof (GstThreadSchedulerTask),
112 (GInstanceInitFunc) gst_thread_scheduler_task_init
116 g_type_register_static (GST_TYPE_TASK,
117 "GstThreadSchedulerTask", &object_info, 0);
123 gst_thread_scheduler_task_class_init (gpointer klass, gpointer class_data)
125 GstTaskClass *task = GST_TASK_CLASS (klass);
127 task->start = gst_thread_scheduler_task_start;
128 task->stop = gst_thread_scheduler_task_stop;
129 task->pause = gst_thread_scheduler_task_pause;
133 gst_thread_scheduler_task_init (GstThreadSchedulerTask * task)
135 GST_TASK (task)->state = GST_TASK_STOPPED;
139 gst_thread_scheduler_task_start (GstTask * task)
141 GstThreadSchedulerTask *ttask = GST_THREAD_SCHEDULER_TASK (task);
142 GstThreadScheduler *tsched =
143 GST_THREAD_SCHEDULER (GST_OBJECT_PARENT (GST_OBJECT (task)));
145 GStaticRecMutex *lock;
147 GST_DEBUG_OBJECT (task, "Starting task %p", task);
149 if ((lock = GST_TASK_GET_LOCK (task)) == NULL) {
150 lock = g_new (GStaticRecMutex, 1);
151 g_static_rec_mutex_init (lock);
152 GST_TASK_GET_LOCK (task) = lock;
156 old = GST_TASK_CAST (ttask)->state;
157 GST_TASK_CAST (ttask)->state = GST_TASK_STARTED;
159 case GST_TASK_STOPPED:
160 gst_object_ref (GST_OBJECT (task));
161 g_thread_pool_push (tsched->pool, task, NULL);
163 case GST_TASK_PAUSED:
164 GST_TASK_SIGNAL (ttask);
166 case GST_TASK_STARTED:
175 gst_thread_scheduler_task_stop (GstTask * task)
177 GstThreadSchedulerTask *ttask = GST_THREAD_SCHEDULER_TASK (task);
180 GST_DEBUG_OBJECT (task, "Stopping task %p", task);
183 old = GST_TASK_CAST (ttask)->state;
184 GST_TASK_CAST (ttask)->state = GST_TASK_STOPPED;
186 case GST_TASK_STOPPED:
188 case GST_TASK_PAUSED:
189 GST_TASK_SIGNAL (ttask);
191 case GST_TASK_STARTED:
200 gst_thread_scheduler_task_pause (GstTask * task)
202 GstThreadSchedulerTask *ttask = GST_THREAD_SCHEDULER_TASK (task);
203 GstThreadScheduler *tsched =
204 GST_THREAD_SCHEDULER (GST_OBJECT_PARENT (GST_OBJECT (task)));
207 GST_DEBUG_OBJECT (task, "Pausing task %p", task);
210 old = GST_TASK_CAST (ttask)->state;
211 GST_TASK_CAST (ttask)->state = GST_TASK_PAUSED;
213 case GST_TASK_STOPPED:
214 gst_object_ref (GST_OBJECT (task));
215 g_thread_pool_push (tsched->pool, task, NULL);
217 case GST_TASK_PAUSED:
219 case GST_TASK_STARTED:
227 static void gst_thread_scheduler_class_init (gpointer g_class, gpointer data);
228 static void gst_thread_scheduler_init (GstThreadScheduler * object);
231 gst_thread_scheduler_get_type (void)
233 static GType object_type = 0;
235 if (object_type == 0) {
236 static const GTypeInfo object_info = {
237 sizeof (GstThreadSchedulerClass),
240 gst_thread_scheduler_class_init,
243 sizeof (GstThreadScheduler),
245 (GInstanceInitFunc) gst_thread_scheduler_init
249 g_type_register_static (GST_TYPE_SCHEDULER,
250 "GstThreadScheduler", &object_info, 0);
255 static void gst_thread_scheduler_setup (GstScheduler * sched);
256 static void gst_thread_scheduler_reset (GstScheduler * sched);
257 static GstTask *gst_thread_scheduler_create_task (GstScheduler * sched,
258 GstTaskFunction func, gpointer data);
261 gst_thread_scheduler_class_init (gpointer klass, gpointer class_data)
263 GstSchedulerClass *scheduler = GST_SCHEDULER_CLASS (klass);
265 scheduler->setup = gst_thread_scheduler_setup;
266 scheduler->reset = gst_thread_scheduler_reset;
267 scheduler->create_task = gst_thread_scheduler_create_task;
271 gst_thread_scheduler_func (GstThreadSchedulerTask * ttask,
272 GstThreadScheduler * sched)
274 GstTask *task = GST_TASK (ttask);
276 GST_DEBUG_OBJECT (sched, "Entering task %p, thread %p", task,
279 /* locking order is TASK_LOCK, LOCK */
280 GST_TASK_LOCK (task);
282 while (G_LIKELY (task->state != GST_TASK_STOPPED)) {
283 while (G_UNLIKELY (task->state == GST_TASK_PAUSED)) {
284 GST_TASK_UNLOCK (task);
285 GST_TASK_SIGNAL (task);
286 GST_TASK_WAIT (task);
288 /* locking order.. */
289 GST_TASK_LOCK (task);
291 if (task->state == GST_TASK_STOPPED)
296 task->func (task->data);
302 GST_TASK_UNLOCK (task);
304 GST_DEBUG_OBJECT (sched, "Exit task %p, thread %p", task, g_thread_self ());
306 gst_object_unref (GST_OBJECT (task));
310 gst_thread_scheduler_init (GstThreadScheduler * scheduler)
312 scheduler->pool = g_thread_pool_new (
313 (GFunc) gst_thread_scheduler_func, scheduler, -1, FALSE, NULL);
317 gst_thread_scheduler_create_task (GstScheduler * sched, GstTaskFunction func,
320 GstThreadSchedulerTask *task;
323 GST_THREAD_SCHEDULER_TASK (g_object_new (GST_TYPE_THREAD_SCHEDULER_TASK,
325 gst_object_set_parent (GST_OBJECT (task), GST_OBJECT (sched));
326 GST_TASK_CAST (task)->func = func;
327 GST_TASK_CAST (task)->data = data;
329 GST_DEBUG_OBJECT (sched, "Created task %p", task);
331 return GST_TASK_CAST (task);
335 gst_thread_scheduler_setup (GstScheduler * sched)
340 gst_thread_scheduler_reset (GstScheduler * sched)
345 plugin_init (GstPlugin * plugin)
347 GstSchedulerFactory *factory;
349 GST_DEBUG_CATEGORY_INIT (debug_scheduler, "thread", 0, "thread scheduler");
351 factory = gst_scheduler_factory_new ("thread",
352 "A scheduler using threads", GST_TYPE_THREAD_SCHEDULER);
356 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
360 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "gstthreadscheduler",
361 "a thread scheduler", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE,