diff options
author | Marco Pesenti Gritti <mpg@redhat.com> | 2005-06-07 09:20:35 (GMT) |
---|---|---|
committer | Marco Pesenti Gritti <marco@src.gnome.org> | 2005-06-07 09:20:35 (GMT) |
commit | 421d3d8b0f2f2432ec02f57677da2964d339f2d8 (patch) | |
tree | ac1ccd139b4b99b15b8f355e3b8aeca79e439621 /backend/ev-job-queue.c | |
parent | 2380ada377881c8e6bf00368f713ebd72e355dda (diff) |
Add an async renderer interface (method + callback) which is useful for
2005-06-07 Marco Pesenti Gritti <mpg@redhat.com>
* backend/Makefile.am:
* backend/ev-async-renderer.c: (ev_async_renderer_get_type),
(ev_async_renderer_class_init), (ev_async_renderer_render_pixbuf):
* backend/ev-async-renderer.h:
Add an async renderer interface (method + callback) which
is useful for backends like ps.
* backend/ev-job-queue.c: (remove_job_from_async_queue),
(add_job_to_async_queue), (job_finished_cb), (handle_job),
(ev_job_queue_run_next), (ev_job_queue_init), (find_queue),
(ev_job_queue_add_job), (move_job_async), (move_job),
(ev_job_queue_update_job), (ev_job_queue_remove_job):
Add queues for async renderer, these are executed on the
main thread.
* backend/ev-jobs.c: (ev_job_render_new), (render_finished_cb),
(ev_job_render_run):
* backend/ev-jobs.h:
If the backend support async renderer interface use it.
* ps/ps-document.c: (ps_document_init), (push_pixbuf),
(setup_pixmap), (ps_document_get_type),
(ps_async_renderer_render_pixbuf),
(ps_document_document_iface_init), (ps_async_renderer_iface_init):
Implement async renderer interface.
Diffstat (limited to 'backend/ev-job-queue.c')
-rw-r--r-- | backend/ev-job-queue.c | 241 |
1 files changed, 181 insertions, 60 deletions
diff --git a/backend/ev-job-queue.c b/backend/ev-job-queue.c index 72470ee..1b3e496 100644 --- a/backend/ev-job-queue.c +++ b/backend/ev-job-queue.c @@ -13,6 +13,14 @@ static GQueue *render_queue_low = NULL; static GQueue *thumbnail_queue_high = NULL; static GQueue *thumbnail_queue_low = NULL; +/* Queues used for backends supporting EvAsyncRender interface, + they are executed on the main thread */ +static GQueue *async_render_queue_high = NULL; +static GQueue *async_render_queue_low = NULL; +static gboolean async_rendering = FALSE; + +static void ev_job_queue_run_next (void); + static gboolean remove_job_from_queue_locked (GQueue *queue, EvJob *job) { @@ -28,6 +36,19 @@ remove_job_from_queue_locked (GQueue *queue, EvJob *job) return FALSE; } +static gboolean +remove_job_from_async_queue (GQueue *queue, EvJob *job) +{ + return remove_job_from_queue_locked (queue, job); +} + +static void +add_job_to_async_queue (GQueue *queue, EvJob *job) +{ + g_object_ref (job); + g_queue_push_tail (queue, job); +} + static void add_job_to_queue_locked (GQueue *queue, EvJob *job) @@ -37,7 +58,6 @@ add_job_to_queue_locked (GQueue *queue, g_cond_broadcast (render_cond); } - static gboolean notify_finished (GObject *job) { @@ -46,12 +66,29 @@ notify_finished (GObject *job) return FALSE; } +static void +job_finished_cb (EvJob *job) +{ + g_object_unref (job); + async_rendering = FALSE; + ev_job_queue_run_next (); +} static void handle_job (EvJob *job) { g_object_ref (G_OBJECT (job)); + if (EV_JOB (job)->async) { + async_rendering = TRUE; + if (EV_IS_JOB_RENDER (job)) { + g_signal_connect (job, "finished", + G_CALLBACK (job_finished_cb), NULL); + } else { + g_assert_not_reached (); + } + } + if (EV_IS_JOB_THUMBNAIL (job)) ev_job_thumbnail_run (EV_JOB_THUMBNAIL (job)); else if (EV_IS_JOB_LINKS (job)) @@ -59,11 +96,13 @@ handle_job (EvJob *job) else if (EV_IS_JOB_RENDER (job)) ev_job_render_run (EV_JOB_RENDER (job)); - /* We let the idle own a ref, as we (the queue) are done with the job. */ - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc) notify_finished, - job, - g_object_unref); + if (!EV_JOB (job)->async) { + /* We let the idle own a ref, as we (the queue) are done with the job. */ + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc) notify_finished, + job, + g_object_unref); + } } static EvJob * @@ -129,6 +168,24 @@ ev_render_thread (gpointer data) } +static void +ev_job_queue_run_next (void) +{ + EvJob *job; + + job = (EvJob *) g_queue_pop_head (async_render_queue_high); + + if (job == NULL) { + job = (EvJob *) g_queue_pop_head (async_render_queue_low); + } + + /* Now that we have our job, we handle it */ + if (job) { + handle_job (job); + g_object_unref (G_OBJECT (job)); + } +} + /* Public Functions */ void ev_job_queue_init (void) @@ -141,6 +198,8 @@ ev_job_queue_init (void) links_queue = g_queue_new (); render_queue_high = g_queue_new (); render_queue_low = g_queue_new (); + async_render_queue_high = g_queue_new (); + async_render_queue_low = g_queue_new (); thumbnail_queue_high = g_queue_new (); thumbnail_queue_low = g_queue_new (); @@ -152,19 +211,28 @@ static GQueue * find_queue (EvJob *job, EvJobPriority priority) { - if (EV_IS_JOB_RENDER (job)) { - if (priority == EV_JOB_PRIORITY_HIGH) - return render_queue_high; - else - return render_queue_low; - } else if (EV_IS_JOB_THUMBNAIL (job)) { - if (priority == EV_JOB_PRIORITY_HIGH) - return thumbnail_queue_high; - else - return thumbnail_queue_low; - } else if (EV_IS_JOB_LINKS (job)) { - /* the priority doesn't effect links */ - return links_queue; + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return async_render_queue_high; + else + return async_render_queue_low; + } + } else { + if (EV_IS_JOB_RENDER (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return render_queue_high; + else + return render_queue_low; + } else if (EV_IS_JOB_THUMBNAIL (job)) { + if (priority == EV_JOB_PRIORITY_HIGH) + return thumbnail_queue_high; + else + return thumbnail_queue_low; + } else if (EV_IS_JOB_LINKS (job)) { + /* the priority doesn't effect links */ + return links_queue; + } } g_assert_not_reached (); @@ -181,9 +249,52 @@ ev_job_queue_add_job (EvJob *job, queue = find_queue (job, priority); + if (!EV_JOB (job)->async) { + g_mutex_lock (ev_queue_mutex); + add_job_to_queue_locked (queue, job); + g_mutex_unlock (ev_queue_mutex); + } else { + add_job_to_async_queue (queue, job); + if (!async_rendering) { + ev_job_queue_run_next (); + } + } +} + +static gboolean +move_job_async (EvJob *job, GQueue *old_queue, GQueue *new_queue) +{ + gboolean retval = FALSE; + + g_object_ref (job); + + if (remove_job_from_queue_locked (old_queue, job)) { + add_job_to_async_queue (new_queue, job); + retval = TRUE; + } + + g_object_unref (job); + + return retval; +} + +static gboolean +move_job (EvJob *job, GQueue *old_queue, GQueue *new_queue) +{ + gboolean retval = FALSE; + g_mutex_lock (ev_queue_mutex); - add_job_to_queue_locked (queue, job); + g_object_ref (job); + + if (remove_job_from_queue_locked (old_queue, job)) { + add_job_to_queue_locked (new_queue, job); + retval = TRUE; + } + + g_object_unref (job); g_mutex_unlock (ev_queue_mutex); + + return retval; } gboolean @@ -194,38 +305,39 @@ ev_job_queue_update_job (EvJob *job, g_return_val_if_fail (EV_IS_JOB (job), FALSE); - g_mutex_lock (ev_queue_mutex); - g_object_ref (job); - - if (EV_IS_JOB_THUMBNAIL (job)) { - if (new_priority == EV_JOB_PRIORITY_LOW) { - if (remove_job_from_queue_locked (thumbnail_queue_high, job)) { - add_job_to_queue_locked (thumbnail_queue_low, job); - retval = TRUE; - } - } else if (new_priority == EV_JOB_PRIORITY_HIGH) { - if (remove_job_from_queue_locked (thumbnail_queue_low, job)) { - add_job_to_queue_locked (thumbnail_queue_high, job); - retval = TRUE; + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job_async (job, async_render_queue_high, + async_render_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job_async (job, async_render_queue_low, + async_render_queue_high); } + } else { + g_assert_not_reached (); } - } else if (EV_IS_JOB_RENDER (job)) { - if (new_priority == EV_JOB_PRIORITY_LOW) { - if (remove_job_from_queue_locked (render_queue_high, job)) { - add_job_to_queue_locked (render_queue_low, job); - retval = TRUE; + } else { + if (EV_IS_JOB_THUMBNAIL (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job (job, thumbnail_queue_high, + thumbnail_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job (job, thumbnail_queue_low, + thumbnail_queue_high); } - } else if (new_priority == EV_JOB_PRIORITY_HIGH) { - if (remove_job_from_queue_locked (render_queue_low, job)) { - add_job_to_queue_locked (render_queue_high, job); - retval = TRUE; + } else if (EV_IS_JOB_RENDER (job)) { + if (new_priority == EV_JOB_PRIORITY_LOW) { + retval = move_job (job, render_queue_high, + render_queue_low); + } else if (new_priority == EV_JOB_PRIORITY_HIGH) { + retval = move_job (job, render_queue_low, + render_queue_high); } + } else { + g_assert_not_reached (); } - } else { - /* We don't have a priority queue for any of the other jobs */ - } - g_object_unref (job); - g_mutex_unlock (ev_queue_mutex); + } return retval; } @@ -237,22 +349,31 @@ ev_job_queue_remove_job (EvJob *job) g_return_val_if_fail (EV_IS_JOB (job), FALSE); - g_mutex_lock (ev_queue_mutex); - - if (EV_IS_JOB_THUMBNAIL (job)) { - retval = remove_job_from_queue_locked (thumbnail_queue_high, job); - retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job); - } else if (EV_IS_JOB_RENDER (job)) { - retval = remove_job_from_queue_locked (render_queue_high, job); - retval = retval || remove_job_from_queue_locked (render_queue_low, job); - } else if (EV_IS_JOB_LINKS (job)) { - retval = remove_job_from_queue_locked (links_queue, job); + if (EV_JOB (job)->async) { + if (EV_IS_JOB_RENDER (job)) { + retval = remove_job_from_async_queue (async_render_queue_high, job); + retval = retval || remove_job_from_async_queue (async_render_queue_low, job); + } else { + g_assert_not_reached (); + } } else { - g_assert_not_reached (); + g_mutex_lock (ev_queue_mutex); + + if (EV_IS_JOB_THUMBNAIL (job)) { + retval = remove_job_from_queue_locked (thumbnail_queue_high, job); + retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job); + } else if (EV_IS_JOB_RENDER (job)) { + retval = remove_job_from_queue_locked (render_queue_high, job); + retval = retval || remove_job_from_queue_locked (render_queue_low, job); + } else if (EV_IS_JOB_LINKS (job)) { + retval = remove_job_from_queue_locked (links_queue, job); + } else { + g_assert_not_reached (); + } + + g_mutex_unlock (ev_queue_mutex); } - g_mutex_unlock (ev_queue_mutex); - return retval; } |