summaryrefslogtreecommitdiff
path: root/src/eom-job-queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eom-job-queue.c')
-rw-r--r--src/eom-job-queue.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/eom-job-queue.c b/src/eom-job-queue.c
new file mode 100644
index 0000000..93ed903
--- /dev/null
+++ b/src/eom-job-queue.c
@@ -0,0 +1,238 @@
+/* Eye Of Mate - Jobs Queue
+ *
+ * Copyright (C) 2006 The Free Software Foundation
+ *
+ * Author: Lucas Rocha <[email protected]>
+ *
+ * Based on evince code (shell/ev-job-queue.c) by:
+ * - Martin Kretzschmar <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "eom-jobs.h"
+#include "eom-job-queue.h"
+
+static GCond *render_cond = NULL;
+static GMutex *eom_queue_mutex = NULL;
+
+static GQueue *thumbnail_queue = NULL;
+static GQueue *load_queue = NULL;
+static GQueue *model_queue = NULL;
+static GQueue *transform_queue = NULL;
+static GQueue *save_queue = NULL;
+static GQueue *copy_queue = NULL;
+
+static gboolean
+remove_job_from_queue (GQueue *queue, EomJob *job)
+{
+ GList *list;
+
+ list = g_queue_find (queue, job);
+
+ if (list) {
+ g_object_unref (G_OBJECT (job));
+ g_queue_delete_link (queue, list);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+add_job_to_queue_locked (GQueue *queue, EomJob *job)
+{
+ g_object_ref (job);
+ g_queue_push_tail (queue, job);
+ g_cond_broadcast (render_cond);
+}
+
+static gboolean
+notify_finished (GObject *job)
+{
+ eom_job_finished (EOM_JOB (job));
+
+ return FALSE;
+}
+
+static void
+handle_job (EomJob *job)
+{
+ g_object_ref (G_OBJECT (job));
+
+ // Do the EOM_JOB cast for safety
+ eom_job_run (EOM_JOB (job));
+
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc) notify_finished,
+ job,
+ g_object_unref);
+}
+
+static gboolean
+no_jobs_available_unlocked (void)
+{
+ return g_queue_is_empty (load_queue) &&
+ g_queue_is_empty (transform_queue) &&
+ g_queue_is_empty (thumbnail_queue) &&
+ g_queue_is_empty (model_queue) &&
+ g_queue_is_empty (save_queue) &&
+ g_queue_is_empty (copy_queue);
+}
+
+static EomJob *
+search_for_jobs_unlocked (void)
+{
+ EomJob *job;
+
+ job = (EomJob *) g_queue_pop_head (load_queue);
+ if (job)
+ return job;
+
+ job = (EomJob *) g_queue_pop_head (transform_queue);
+ if (job)
+ return job;
+
+ job = (EomJob *) g_queue_pop_head (thumbnail_queue);
+ if (job)
+ return job;
+
+ job = (EomJob *) g_queue_pop_head (model_queue);
+ if (job)
+ return job;
+
+ job = (EomJob *) g_queue_pop_head (save_queue);
+ if (job)
+ return job;
+
+ job = (EomJob *) g_queue_pop_head (copy_queue);
+ if (job)
+ return job;
+
+ return NULL;
+}
+
+static gpointer
+eom_render_thread (gpointer data)
+{
+ while (TRUE) {
+ EomJob *job;
+
+ g_mutex_lock (eom_queue_mutex);
+
+ if (no_jobs_available_unlocked ()) {
+ g_cond_wait (render_cond, eom_queue_mutex);
+ }
+
+ job = search_for_jobs_unlocked ();
+
+ g_mutex_unlock (eom_queue_mutex);
+
+ /* Now that we have our job, we handle it */
+ if (job) {
+ handle_job (job);
+ g_object_unref (G_OBJECT (job));
+ }
+ }
+ return NULL;
+
+}
+
+void
+eom_job_queue_init (void)
+{
+ if (!g_thread_supported ()) g_thread_init (NULL);
+
+ render_cond = g_cond_new ();
+ eom_queue_mutex = g_mutex_new ();
+
+ thumbnail_queue = g_queue_new ();
+ load_queue = g_queue_new ();
+ model_queue = g_queue_new ();
+ transform_queue = g_queue_new ();
+ save_queue = g_queue_new ();
+ copy_queue = g_queue_new ();
+
+ g_thread_create (eom_render_thread, NULL, FALSE, NULL);
+}
+
+static GQueue *
+find_queue (EomJob *job)
+{
+ if (EOM_IS_JOB_THUMBNAIL (job)) {
+ return thumbnail_queue;
+ } else if (EOM_IS_JOB_LOAD (job)) {
+ return load_queue;
+ } else if (EOM_IS_JOB_MODEL (job)) {
+ return model_queue;
+ } else if (EOM_IS_JOB_TRANSFORM (job)) {
+ return transform_queue;
+ } else if (EOM_IS_JOB_SAVE (job)) {
+ return save_queue;
+ } else if (EOM_IS_JOB_COPY (job)) {
+ return copy_queue;
+ }
+
+ g_assert_not_reached ();
+
+ return NULL;
+}
+
+void
+eom_job_queue_add_job (EomJob *job)
+{
+ GQueue *queue;
+
+ g_return_if_fail (EOM_IS_JOB (job));
+
+ queue = find_queue (job);
+
+ g_mutex_lock (eom_queue_mutex);
+
+ add_job_to_queue_locked (queue, job);
+
+ g_mutex_unlock (eom_queue_mutex);
+}
+
+gboolean
+eom_job_queue_remove_job (EomJob *job)
+{
+ gboolean retval = FALSE;
+
+ g_return_val_if_fail (EOM_IS_JOB (job), FALSE);
+
+ g_mutex_lock (eom_queue_mutex);
+
+ if (EOM_IS_JOB_THUMBNAIL (job)) {
+ retval = remove_job_from_queue (thumbnail_queue, job);
+ } else if (EOM_IS_JOB_LOAD (job)) {
+ retval = remove_job_from_queue (load_queue, job);
+ } else if (EOM_IS_JOB_MODEL (job)) {
+ retval = remove_job_from_queue (model_queue, job);
+ } else if (EOM_IS_JOB_TRANSFORM (job)) {
+ retval = remove_job_from_queue (transform_queue, job);
+ } else if (EOM_IS_JOB_SAVE (job)) {
+ retval = remove_job_from_queue (save_queue, job);
+ } else if (EOM_IS_JOB_COPY (job)) {
+ retval = remove_job_from_queue (copy_queue, job);
+ } else {
+ g_assert_not_reached ();
+ }
+
+ g_mutex_unlock (eom_queue_mutex);
+
+ return retval;
+}