Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/shell/ev-job-queue.c
diff options
context:
space:
mode:
authorCarlos Garcia Campos <carlosgc@gnome.org>2008-08-03 11:01:28 (GMT)
committer Carlos Garcia Campos <carlosgc@src.gnome.org>2008-08-03 11:01:28 (GMT)
commite71d27db284ccf431167816167bf72f1e23c334d (patch)
tree1f1d9aff48947adcbaecbdfe3b181f6adb00cb3e /shell/ev-job-queue.c
parenta68744f0210c49bcaded78edd29e7198bf58f8e7 (diff)
Rework the jobs system in order to make it simpler and more extensible. It
2008-08-03 Carlos Garcia Campos <carlosgc@gnome.org> * libdocument/ev-document.[ch]: (ev_document_doc_mutex_trylock), (ev_document_fc_mutex_trylock): * shell/Makefile.am: * shell/ev-job-queue.[ch]: * shell/ev-job-scheduler.[ch]: * shell/ev-jobs.[ch]: (ev_job_init), (ev_job_dispose), (ev_job_class_init), (emit_finished), (ev_job_emit_finished), (ev_job_run), (ev_job_cancel), (ev_job_failed), (ev_job_failed_from_error), (ev_job_succeeded), (ev_job_is_finished), (ev_job_is_failed), (ev_job_get_run_mode), (ev_job_set_run_mode), (ev_job_links_init), (ev_job_links_run), (ev_job_links_class_init), (ev_job_render_init), (notify_page_ready), (ev_job_render_page_ready), (ev_job_render_run), (ev_job_render_class_init), (ev_job_thumbnail_init), (ev_job_thumbnail_run), (ev_job_thumbnail_class_init), (ev_job_fonts_init), (ev_job_fonts_run), (ev_job_fonts_class_init), (ev_job_load_init), (ev_job_load_run), (ev_job_load_class_init), (ev_job_save_init), (ev_job_save_dispose), (ev_job_save_run), (ev_job_save_class_init), (ev_job_print_init), (ev_job_print_dispose), (ev_job_print_run), (ev_job_print_class_init): * shell/ev-page-cache.c: * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info), (check_job_size_and_unref), (move_one_job), (copy_job_to_job_info), (add_job), (ev_pixbuf_cache_add_jobs_if_needed): * shell/ev-properties-fonts.c: (ev_properties_fonts_dispose), (job_fonts_finished_cb), (job_fonts_updated_cb), (ev_properties_fonts_set_document): * shell/ev-sidebar-links.c: (ev_sidebar_links_dispose), (ev_sidebar_links_set_document): * shell/ev-sidebar-thumbnails.c: (clear_range), (add_range), (ev_sidebar_thumbnails_set_document), (ev_sidebar_thumbnails_clear_job): * shell/ev-view-private.h: * shell/ev-view.c: * shell/ev-window.c: (ev_window_clear_thumbnail_job), (ev_window_refresh_window_thumbnail), (password_dialog_response), (ev_window_clear_load_job), (ev_window_clear_reload_job), (ev_window_load_job_cb), (ev_window_reload_job_cb), (window_open_file_copy_ready_cb), (ev_window_open_uri), (ev_window_reload_document), (ev_window_clear_save_job), (ev_window_save_job_cb), (file_save_dialog_response_cb), (ev_window_clear_print_job), (ev_window_print_job_cb), (ev_window_print_dialog_response_cb): * shell/main.c: (main): Rework the jobs system in order to make it simpler and more extensible. It allows to run jobs in the main loop instead of using a thread when it's appropriate like the fonts job. Now it's also possible to cancel jobs that are currently running. svn path=/trunk/; revision=3092
Diffstat (limited to 'shell/ev-job-queue.c')
-rw-r--r--shell/ev-job-queue.c517
1 files changed, 0 insertions, 517 deletions
diff --git a/shell/ev-job-queue.c b/shell/ev-job-queue.c
deleted file mode 100644
index 8280aab..0000000
--- a/shell/ev-job-queue.c
+++ /dev/null
@@ -1,517 +0,0 @@
-#include <config.h>
-#include "ev-job-queue.h"
-
-/* Like glib calling convention, all functions with _locked in their name assume
- * that we've already locked the doc mutex and can freely and safely access
- * data.
- */
-GCond *render_cond = NULL;
-GMutex *ev_queue_mutex = NULL;
-
-static GQueue *links_queue = NULL;
-static GQueue *render_queue_high = NULL;
-static GQueue *render_queue_low = NULL;
-static GQueue *thumbnail_queue_high = NULL;
-static GQueue *thumbnail_queue_low = NULL;
-static GQueue *load_queue = NULL;
-static GQueue *save_queue = NULL;
-static GQueue *fonts_queue = NULL;
-static GQueue *print_queue = 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)
-{
- 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 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);
-}
-
-/**
- * add_job_to_queue_locked:
- * @queue: a #GQueue where the #EvJob will be added.
- * @job: an #EvJob to be added to the specified #GQueue.
- *
- * Add the #EvJob to the specified #GQueue and woke up the ev_render_thread who
- * is waiting for render_cond.
- */
-static void
-add_job_to_queue_locked (GQueue *queue,
- EvJob *job)
-{
- g_object_ref (job);
- g_queue_push_tail (queue, job);
- g_cond_broadcast (render_cond);
-}
-
-/**
- * notify_finished:
- * @job: the object that signal will be reseted.
- *
- * It does emit the job finished signal and returns %FALSE.
- *
- * Returns: %FALSE.
- */
-static gboolean
-notify_finished (GObject *job)
-{
- ev_job_finished (EV_JOB (job));
-
- return FALSE;
-}
-
-/**
- * job_finished_cb:
- * @job: the #EvJob that has been handled.
- *
- * It does finish the job last work and look if there is any more job to be
- * handled.
- */
-static void
-job_finished_cb (EvJob *job)
-{
- g_object_unref (job);
- async_rendering = FALSE;
- ev_job_queue_run_next ();
-}
-
-/**
- * handle_job:
- * @job: the #EvJob to be handled.
- *
- * First, it does check if the job is async and then it does attend it if
- * possible giving a failed assertion otherwise. If the job isn't async it does
- * attend it and notify that the job has been finished.
- */
-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))
- ev_job_links_run (EV_JOB_LINKS (job));
- else if (EV_IS_JOB_LOAD (job))
- ev_job_load_run (EV_JOB_LOAD (job));
- else if (EV_IS_JOB_SAVE (job))
- ev_job_save_run (EV_JOB_SAVE (job));
- else if (EV_IS_JOB_RENDER (job))
- ev_job_render_run (EV_JOB_RENDER (job));
- else if (EV_IS_JOB_FONTS (job))
- ev_job_fonts_run (EV_JOB_FONTS (job));
- else if (EV_IS_JOB_PRINT (job))
- ev_job_print_run (EV_JOB_PRINT (job));
-
- 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);
- }
-}
-
-/**
- * search_for_jobs_unlocked:
- *
- * Check if there is any job at the synchronized queues and return any existing
- * job in them taking in account the next priority:
- *
- * render_queue_high >
- * thumbnail_queue_high >
- * render_queue_low >
- * links_queue >
- * load_queue >
- * thumbnail_queue_low >
- * fonts_queue >
- * print_queue >
- *
- * Returns: an available #EvJob in the queues taking in account stablished queue
- * priorities.
- */
-static EvJob *
-search_for_jobs_unlocked (void)
-{
- EvJob *job;
-
- job = (EvJob *) g_queue_pop_head (render_queue_high);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (thumbnail_queue_high);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (render_queue_low);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (links_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (load_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (save_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (thumbnail_queue_low);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (fonts_queue);
- if (job)
- return job;
-
- job = (EvJob *) g_queue_pop_head (print_queue);
- if (job)
- return job;
-
- return NULL;
-}
-
-/**
- * no_jobs_available_unlocked:
- *
- * Looks if there is any job at render, links, load, thumbnail. fonts and print
- * queues.
- *
- * Returns: %TRUE if the render, links, load, thumbnail, fonts and print queues
- * are empty, %FALSE in other case.
- */
-static gboolean
-no_jobs_available_unlocked (void)
-{
- return g_queue_is_empty (render_queue_high)
- && g_queue_is_empty (render_queue_low)
- && g_queue_is_empty (links_queue)
- && g_queue_is_empty (load_queue)
- && g_queue_is_empty (save_queue)
- && g_queue_is_empty (thumbnail_queue_high)
- && g_queue_is_empty (thumbnail_queue_low)
- && g_queue_is_empty (fonts_queue)
- && g_queue_is_empty (print_queue);
-}
-
-/* the thread mainloop function */
-/**
- * ev_render_thread:
- * @data: data passed to the thread.
- *
- * The thread mainloop function. It does wait for any available job in synced
- * queues to handle it.
- *
- * Returns: the return value of the thread, which will be returned by
- * g_thread_join().
- */
-static gpointer
-ev_render_thread (gpointer data)
-{
- while (TRUE) {
- EvJob *job;
-
- g_mutex_lock (ev_queue_mutex);
- if (no_jobs_available_unlocked ()) {
- g_cond_wait (render_cond, ev_queue_mutex);
- }
-
- job = search_for_jobs_unlocked ();
- g_mutex_unlock (ev_queue_mutex);
-
- /* Now that we have our job, we handle it */
- if (job) {
- handle_job (job);
- g_object_unref (G_OBJECT (job));
- }
- }
- return NULL;
-
-}
-
-/**
- * ev_job_queue_run_next:
- *
- * It does look for any job on the render high priority queue first and after
- * in the render low priority one, and then it does handle it.
- */
-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 */
-/**
- * ev_job_queue_init:
- *
- * Creates a new cond, new mutex, a thread for evince job handling and inits
- * every queue.
- */
-void
-ev_job_queue_init (void)
-{
- if (!g_thread_supported ()) g_thread_init (NULL);
-
- render_cond = g_cond_new ();
- ev_queue_mutex = g_mutex_new ();
-
- links_queue = g_queue_new ();
- load_queue = g_queue_new ();
- save_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 ();
- fonts_queue = g_queue_new ();
- print_queue = g_queue_new ();
-
- g_thread_create (ev_render_thread, NULL, FALSE, NULL);
-
-}
-
-static GQueue *
-find_queue (EvJob *job,
- EvJobPriority priority)
-{
- 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_LOAD (job)) {
- /* the priority doesn't effect load */
- return load_queue;
- } else if (EV_IS_JOB_SAVE (job)) {
- /* the priority doesn't effect save */
- return save_queue;
- } else if (EV_IS_JOB_LINKS (job)) {
- /* the priority doesn't effect links */
- return links_queue;
- } else if (EV_IS_JOB_FONTS (job)) {
- /* the priority doesn't effect fonts */
- return fonts_queue;
- } else if (EV_IS_JOB_PRINT (job)) {
- /* the priority doesn't effect print */
- return print_queue;
- }
- }
-
- g_assert_not_reached ();
- return NULL;
-}
-
-void
-ev_job_queue_add_job (EvJob *job,
- EvJobPriority priority)
-{
- GQueue *queue;
-
- g_return_if_fail (EV_IS_JOB (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);
- 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
-ev_job_queue_update_job (EvJob *job,
- EvJobPriority new_priority)
-{
- gboolean retval = FALSE;
-
- g_return_val_if_fail (EV_IS_JOB (job), FALSE);
-
- 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_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 (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 ();
- }
- }
-
- return retval;
-}
-
-gboolean
-ev_job_queue_remove_job (EvJob *job)
-{
- gboolean retval = FALSE;
-
- g_return_val_if_fail (EV_IS_JOB (job), FALSE);
-
- 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_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 if (EV_IS_JOB_LOAD (job)) {
- retval = remove_job_from_queue_locked (load_queue, job);
- } else if (EV_IS_JOB_SAVE (job)) {
- retval = remove_job_from_queue_locked (save_queue, job);
- } else if (EV_IS_JOB_FONTS (job)) {
- retval = remove_job_from_queue_locked (fonts_queue, job);
- } else if (EV_IS_JOB_PRINT (job)) {
- retval = remove_job_from_queue_locked (print_queue, job);
- } else {
- g_assert_not_reached ();
- }
-
- g_mutex_unlock (ev_queue_mutex);
- }
-
- return retval;
-}
-
-