Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/backend/ev-job-queue.c
diff options
context:
space:
mode:
authorMarco 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)
commit421d3d8b0f2f2432ec02f57677da2964d339f2d8 (patch)
treeac1ccd139b4b99b15b8f355e3b8aeca79e439621 /backend/ev-job-queue.c
parent2380ada377881c8e6bf00368f713ebd72e355dda (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.c241
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;
}