diff options
Diffstat (limited to 'shell/ev-job-scheduler.c')
-rw-r--r-- | shell/ev-job-scheduler.c | 305 |
1 files changed, 0 insertions, 305 deletions
diff --git a/shell/ev-job-scheduler.c b/shell/ev-job-scheduler.c deleted file mode 100644 index 900714e..0000000 --- a/shell/ev-job-scheduler.c +++ /dev/null @@ -1,305 +0,0 @@ -/* ev-job-scheduler.c - * this file is part of evince, a gnome document viewer - * - * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org> - * - * Evince 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. - * - * Evince 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 "ev-debug.h" -#include "ev-job-scheduler.h" - -typedef struct _EvSchedulerJob { - EvJob *job; - EvJobPriority priority; - GSList *job_link; -} EvSchedulerJob; - -G_LOCK_DEFINE_STATIC(job_list); -static GSList *job_list = NULL; - -static gpointer ev_job_thread_proxy (gpointer data); -static void ev_scheduler_thread_job_cancelled (EvSchedulerJob *job, - GCancellable *cancellable); - -/* EvJobQueue */ -static GQueue queue_urgent = G_QUEUE_INIT; -static GQueue queue_high = G_QUEUE_INIT; -static GQueue queue_low = G_QUEUE_INIT; -static GQueue queue_none = G_QUEUE_INIT; - -static GCond *job_queue_cond = NULL; -static GMutex *job_queue_mutex = NULL; -static GQueue *job_queue[EV_JOB_N_PRIORITIES] = { - &queue_urgent, - &queue_high, - &queue_low, - &queue_none -}; - -static void -ev_job_queue_push (EvSchedulerJob *job, - EvJobPriority priority) -{ - ev_debug_message (DEBUG_JOBS, "%s priority %d", EV_GET_TYPE_NAME (job->job), priority); - - g_mutex_lock (job_queue_mutex); - - g_queue_push_tail (job_queue[priority], job); - g_cond_broadcast (job_queue_cond); - - g_mutex_unlock (job_queue_mutex); -} - -static EvSchedulerJob * -ev_job_queue_get_next_unlocked (void) -{ - gint i; - EvSchedulerJob *job = NULL; - - for (i = EV_JOB_PRIORITY_URGENT; i < EV_JOB_N_PRIORITIES; i++) { - job = (EvSchedulerJob *) g_queue_pop_head (job_queue[i]); - if (job) - break; - } - - ev_debug_message (DEBUG_JOBS, "%s", job ? EV_GET_TYPE_NAME (job->job) : "No jobs in queue"); - - return job; -} - -static gpointer -ev_job_scheduler_init (gpointer data) -{ - job_queue_cond = g_cond_new (); - job_queue_mutex = g_mutex_new (); - g_thread_create (ev_job_thread_proxy, NULL, FALSE, NULL); - - return NULL; -} - -static void -ev_scheduler_job_list_add (EvSchedulerJob *job) -{ - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job)); - - G_LOCK (job_list); - - job_list = g_slist_prepend (job_list, job); - job->job_link = job_list; - - G_UNLOCK (job_list); -} - -static void -ev_scheduler_job_list_remove (EvSchedulerJob *job) -{ - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job)); - - G_LOCK (job_list); - - job_list = g_slist_delete_link (job_list, job->job_link); - - G_UNLOCK (job_list); -} - -static void -ev_scheduler_job_free (EvSchedulerJob *job) -{ - if (!job) - return; - - g_object_unref (job->job); - g_free (job); -} - -static void -ev_scheduler_job_destroy (EvSchedulerJob *job) -{ - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job)); - - if (job->job->run_mode == EV_JOB_RUN_MAIN_LOOP) { - g_signal_handlers_disconnect_by_func (job->job, - G_CALLBACK (ev_scheduler_job_destroy), - job); - } else { - g_signal_handlers_disconnect_by_func (job->job->cancellable, - G_CALLBACK (ev_scheduler_thread_job_cancelled), - job); - } - - ev_scheduler_job_list_remove (job); - ev_scheduler_job_free (job); -} - -static void -ev_scheduler_thread_job_cancelled (EvSchedulerJob *job, - GCancellable *cancellable) -{ - GList *list; - - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job->job)); - - g_mutex_lock (job_queue_mutex); - - /* If the job is not still running, - * remove it from the job queue and job list. - * If the job is currently running, it will be - * destroyed as soon as it finishes. - */ - list = g_queue_find (job_queue[job->priority], job); - if (list) { - g_queue_delete_link (job_queue[job->priority], list); - g_mutex_unlock (job_queue_mutex); - ev_scheduler_job_destroy (job); - } else { - g_mutex_unlock (job_queue_mutex); - } -} - -static void -ev_job_thread (EvJob *job) -{ - gboolean result; - - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job)); - - do { - if (g_cancellable_is_cancelled (job->cancellable)) - result = FALSE; - else - result = ev_job_run (job); - } while (result); -} - -static gboolean -ev_job_idle (EvJob *job) -{ - ev_debug_message (DEBUG_JOBS, "%s", EV_GET_TYPE_NAME (job)); - - if (g_cancellable_is_cancelled (job->cancellable)) - return FALSE; - - return ev_job_run (job); -} - -static gpointer -ev_job_thread_proxy (gpointer data) -{ - while (TRUE) { - EvSchedulerJob *job; - - g_mutex_lock (job_queue_mutex); - job = ev_job_queue_get_next_unlocked (); - if (!job) { - g_cond_wait (job_queue_cond, job_queue_mutex); - g_mutex_unlock (job_queue_mutex); - continue; - } - g_mutex_unlock (job_queue_mutex); - - ev_job_thread (job->job); - ev_scheduler_job_destroy (job); - } - - return NULL; -} - -void -ev_job_scheduler_push_job (EvJob *job, - EvJobPriority priority) -{ - static GOnce once_init = G_ONCE_INIT; - EvSchedulerJob *s_job; - - g_once (&once_init, ev_job_scheduler_init, NULL); - - ev_debug_message (DEBUG_JOBS, "%s pirority %d", EV_GET_TYPE_NAME (job), priority); - - s_job = g_new0 (EvSchedulerJob, 1); - s_job->job = g_object_ref (job); - s_job->priority = priority; - - ev_scheduler_job_list_add (s_job); - - switch (ev_job_get_run_mode (job)) { - case EV_JOB_RUN_THREAD: - g_signal_connect_swapped (job->cancellable, "cancelled", - G_CALLBACK (ev_scheduler_thread_job_cancelled), - s_job); - ev_job_queue_push (s_job, priority); - break; - case EV_JOB_RUN_MAIN_LOOP: - g_signal_connect_swapped (job, "finished", - G_CALLBACK (ev_scheduler_job_destroy), - s_job); - g_signal_connect_swapped (job, "cancelled", - G_CALLBACK (ev_scheduler_job_destroy), - s_job); - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)ev_job_idle, - g_object_ref (job), - (GDestroyNotify)g_object_unref); - break; - default: - g_assert_not_reached (); - } -} - -void -ev_job_scheduler_update_job (EvJob *job, - EvJobPriority priority) -{ - GSList *l; - EvSchedulerJob *s_job = NULL; - gboolean need_resort = FALSE; - - /* Main loop jobs are scheduled inmediately */ - if (ev_job_get_run_mode (job) == EV_JOB_RUN_MAIN_LOOP) - return; - - ev_debug_message (DEBUG_JOBS, "%s pirority %d", EV_GET_TYPE_NAME (job), priority); - - G_LOCK (job_list); - - for (l = job_list; l; l = l->next) { - s_job = (EvSchedulerJob *)l->data; - - if (s_job->job == job) { - need_resort = (s_job->priority != priority); - break; - } - } - - G_UNLOCK (job_list); - - if (need_resort) { - GList *list; - - g_mutex_lock (job_queue_mutex); - - list = g_queue_find (job_queue[s_job->priority], s_job); - if (list) { - ev_debug_message (DEBUG_JOBS, "Moving job %s from pirority %d to %d", - EV_GET_TYPE_NAME (job), s_job->priority, priority); - g_queue_delete_link (job_queue[s_job->priority], list); - g_queue_push_tail (job_queue[priority], s_job); - g_cond_broadcast (job_queue_cond); - } - - g_mutex_unlock (job_queue_mutex); - } -} - |