1 #include "ev-job-queue.h"
3 /* Like glib calling convention, all functions with _locked in their name assume
4 * that we've already locked the doc mutex and can freely and safely access
7 GCond *render_cond = NULL;
8 GMutex *ev_queue_mutex = NULL;
10 static GQueue *links_queue = NULL;
11 static GQueue *render_queue_high = NULL;
12 static GQueue *render_queue_low = NULL;
13 static GQueue *thumbnail_queue_high = NULL;
14 static GQueue *thumbnail_queue_low = NULL;
15 static GQueue *xfer_queue = NULL;
16 static GQueue *fonts_queue = NULL;
17 static GQueue *print_queue = NULL;
19 /* Queues used for backends supporting EvAsyncRender interface,
20 they are executed on the main thread */
21 static GQueue *async_render_queue_high = NULL;
22 static GQueue *async_render_queue_low = NULL;
23 static gboolean async_rendering = FALSE;
25 static void ev_job_queue_run_next (void);
28 remove_job_from_queue_locked (GQueue *queue, EvJob *job)
32 list = g_queue_find (queue, job);
34 g_object_unref (G_OBJECT (job));
35 g_queue_delete_link (queue, list);
43 remove_job_from_async_queue (GQueue *queue, EvJob *job)
45 return remove_job_from_queue_locked (queue, job);
49 add_job_to_async_queue (GQueue *queue, EvJob *job)
52 g_queue_push_tail (queue, job);
56 add_job_to_queue_locked (GQueue *queue,
60 g_queue_push_tail (queue, job);
61 g_cond_broadcast (render_cond);
65 notify_finished (GObject *job)
67 ev_job_finished (EV_JOB (job));
73 job_finished_cb (EvJob *job)
76 async_rendering = FALSE;
77 ev_job_queue_run_next ();
81 handle_job (EvJob *job)
83 g_object_ref (G_OBJECT (job));
85 if (EV_JOB (job)->async) {
86 async_rendering = TRUE;
87 if (EV_IS_JOB_RENDER (job)) {
88 g_signal_connect (job, "finished",
89 G_CALLBACK (job_finished_cb), NULL);
91 g_assert_not_reached ();
95 if (EV_IS_JOB_THUMBNAIL (job))
96 ev_job_thumbnail_run (EV_JOB_THUMBNAIL (job));
97 else if (EV_IS_JOB_LINKS (job))
98 ev_job_links_run (EV_JOB_LINKS (job));
99 else if (EV_IS_JOB_XFER (job))
100 ev_job_xfer_run (EV_JOB_XFER (job));
101 else if (EV_IS_JOB_RENDER (job))
102 ev_job_render_run (EV_JOB_RENDER (job));
103 else if (EV_IS_JOB_FONTS (job))
104 ev_job_fonts_run (EV_JOB_FONTS (job));
105 else if (EV_IS_JOB_PRINT (job))
106 ev_job_print_run (EV_JOB_PRINT (job));
108 if (!EV_JOB (job)->async) {
109 /* We let the idle own a ref, as we (the queue) are done with the job. */
110 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
111 (GSourceFunc) notify_finished,
118 search_for_jobs_unlocked (void)
122 job = (EvJob *) g_queue_pop_head (render_queue_high);
126 job = (EvJob *) g_queue_pop_head (thumbnail_queue_high);
130 job = (EvJob *) g_queue_pop_head (render_queue_low);
134 job = (EvJob *) g_queue_pop_head (links_queue);
138 job = (EvJob *) g_queue_pop_head (xfer_queue);
142 job = (EvJob *) g_queue_pop_head (thumbnail_queue_low);
146 job = (EvJob *) g_queue_pop_head (fonts_queue);
150 job = (EvJob *) g_queue_pop_head (print_queue);
158 no_jobs_available_unlocked (void)
160 return g_queue_is_empty (render_queue_high)
161 && g_queue_is_empty (render_queue_low)
162 && g_queue_is_empty (links_queue)
163 && g_queue_is_empty (xfer_queue)
164 && g_queue_is_empty (thumbnail_queue_high)
165 && g_queue_is_empty (thumbnail_queue_low)
166 && g_queue_is_empty (fonts_queue)
167 && g_queue_is_empty (print_queue);
170 /* the thread mainloop function */
172 ev_render_thread (gpointer data)
177 g_mutex_lock (ev_queue_mutex);
178 if (no_jobs_available_unlocked ()) {
179 g_cond_wait (render_cond, ev_queue_mutex);
182 job = search_for_jobs_unlocked ();
183 g_mutex_unlock (ev_queue_mutex);
185 /* Now that we have our job, we handle it */
188 g_object_unref (G_OBJECT (job));
196 ev_job_queue_run_next (void)
200 job = (EvJob *) g_queue_pop_head (async_render_queue_high);
203 job = (EvJob *) g_queue_pop_head (async_render_queue_low);
206 /* Now that we have our job, we handle it */
209 g_object_unref (G_OBJECT (job));
213 /* Public Functions */
215 ev_job_queue_init (void)
217 if (!g_thread_supported ()) g_thread_init (NULL);
219 render_cond = g_cond_new ();
220 ev_queue_mutex = g_mutex_new ();
222 links_queue = g_queue_new ();
223 xfer_queue = g_queue_new ();
224 render_queue_high = g_queue_new ();
225 render_queue_low = g_queue_new ();
226 async_render_queue_high = g_queue_new ();
227 async_render_queue_low = g_queue_new ();
228 thumbnail_queue_high = g_queue_new ();
229 thumbnail_queue_low = g_queue_new ();
230 fonts_queue = g_queue_new ();
231 print_queue = g_queue_new ();
233 g_thread_create (ev_render_thread, NULL, FALSE, NULL);
238 find_queue (EvJob *job,
239 EvJobPriority priority)
241 if (EV_JOB (job)->async) {
242 if (EV_IS_JOB_RENDER (job)) {
243 if (priority == EV_JOB_PRIORITY_HIGH)
244 return async_render_queue_high;
246 return async_render_queue_low;
249 if (EV_IS_JOB_RENDER (job)) {
250 if (priority == EV_JOB_PRIORITY_HIGH)
251 return render_queue_high;
253 return render_queue_low;
254 } else if (EV_IS_JOB_THUMBNAIL (job)) {
255 if (priority == EV_JOB_PRIORITY_HIGH)
256 return thumbnail_queue_high;
258 return thumbnail_queue_low;
259 } else if (EV_IS_JOB_XFER (job)) {
260 /* the priority doesn't effect xfer */
262 } else if (EV_IS_JOB_LINKS (job)) {
263 /* the priority doesn't effect links */
265 } else if (EV_IS_JOB_FONTS (job)) {
266 /* the priority doesn't effect fonts */
268 } else if (EV_IS_JOB_PRINT (job)) {
269 /* the priority doesn't effect print */
274 g_assert_not_reached ();
279 ev_job_queue_add_job (EvJob *job,
280 EvJobPriority priority)
284 g_return_if_fail (EV_IS_JOB (job));
286 queue = find_queue (job, priority);
288 if (!EV_JOB (job)->async) {
289 g_mutex_lock (ev_queue_mutex);
290 add_job_to_queue_locked (queue, job);
291 g_mutex_unlock (ev_queue_mutex);
293 add_job_to_async_queue (queue, job);
294 if (!async_rendering) {
295 ev_job_queue_run_next ();
301 move_job_async (EvJob *job, GQueue *old_queue, GQueue *new_queue)
303 gboolean retval = FALSE;
307 if (remove_job_from_queue_locked (old_queue, job)) {
308 add_job_to_async_queue (new_queue, job);
312 g_object_unref (job);
318 move_job (EvJob *job, GQueue *old_queue, GQueue *new_queue)
320 gboolean retval = FALSE;
322 g_mutex_lock (ev_queue_mutex);
325 if (remove_job_from_queue_locked (old_queue, job)) {
326 add_job_to_queue_locked (new_queue, job);
330 g_object_unref (job);
331 g_mutex_unlock (ev_queue_mutex);
337 ev_job_queue_update_job (EvJob *job,
338 EvJobPriority new_priority)
340 gboolean retval = FALSE;
342 g_return_val_if_fail (EV_IS_JOB (job), FALSE);
344 if (EV_JOB (job)->async) {
345 if (EV_IS_JOB_RENDER (job)) {
346 if (new_priority == EV_JOB_PRIORITY_LOW) {
347 retval = move_job_async (job, async_render_queue_high,
348 async_render_queue_low);
349 } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
350 retval = move_job_async (job, async_render_queue_low,
351 async_render_queue_high);
354 g_assert_not_reached ();
357 if (EV_IS_JOB_THUMBNAIL (job)) {
358 if (new_priority == EV_JOB_PRIORITY_LOW) {
359 retval = move_job (job, thumbnail_queue_high,
360 thumbnail_queue_low);
361 } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
362 retval = move_job (job, thumbnail_queue_low,
363 thumbnail_queue_high);
365 } else if (EV_IS_JOB_RENDER (job)) {
366 if (new_priority == EV_JOB_PRIORITY_LOW) {
367 retval = move_job (job, render_queue_high,
369 } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
370 retval = move_job (job, render_queue_low,
374 g_assert_not_reached ();
382 ev_job_queue_remove_job (EvJob *job)
384 gboolean retval = FALSE;
386 g_return_val_if_fail (EV_IS_JOB (job), FALSE);
388 if (EV_JOB (job)->async) {
389 if (EV_IS_JOB_RENDER (job)) {
390 retval = remove_job_from_async_queue (async_render_queue_high, job);
391 retval = retval || remove_job_from_async_queue (async_render_queue_low, job);
393 g_assert_not_reached ();
396 g_mutex_lock (ev_queue_mutex);
398 if (EV_IS_JOB_THUMBNAIL (job)) {
399 retval = remove_job_from_queue_locked (thumbnail_queue_high, job);
400 retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job);
401 } else if (EV_IS_JOB_RENDER (job)) {
402 retval = remove_job_from_queue_locked (render_queue_high, job);
403 retval = retval || remove_job_from_queue_locked (render_queue_low, job);
404 } else if (EV_IS_JOB_LINKS (job)) {
405 retval = remove_job_from_queue_locked (links_queue, job);
406 } else if (EV_IS_JOB_XFER (job)) {
407 retval = remove_job_from_queue_locked (xfer_queue, job);
408 } else if (EV_IS_JOB_FONTS (job)) {
409 retval = remove_job_from_queue_locked (fonts_queue, job);
410 } else if (EV_IS_JOB_PRINT (job)) {
411 retval = remove_job_from_queue_locked (print_queue, job);
413 g_assert_not_reached ();
416 g_mutex_unlock (ev_queue_mutex);