1
0
mirror of https://gitlab.gnome.org/GNOME/evince synced 2024-07-05 00:59:07 +00:00

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
This commit is contained in:
Carlos Garcia Campos 2008-08-03 11:01:28 +00:00 committed by Carlos Garcia Campos
parent a68744f021
commit e71d27db28
19 changed files with 1248 additions and 1129 deletions

View File

@ -1,3 +1,58 @@
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.
2008-07-27 Carlos Garcia Campos <carlosgc@gnome.org>
* libdocument/ev-debug.c: (profile_init):

View File

@ -89,6 +89,12 @@ ev_document_doc_mutex_unlock (void)
g_mutex_unlock (ev_document_get_doc_mutex ());
}
gboolean
ev_document_doc_mutex_trylock (void)
{
return g_mutex_trylock (ev_document_get_doc_mutex ());
}
GMutex *
ev_document_get_fc_mutex (void)
{
@ -110,6 +116,12 @@ ev_document_fc_mutex_unlock (void)
g_mutex_unlock (ev_document_get_fc_mutex ());
}
gboolean
ev_document_fc_mutex_trylock (void)
{
return g_mutex_trylock (ev_document_get_fc_mutex ());
}
gboolean
ev_document_load (EvDocument *document,
const char *uri,

View File

@ -101,11 +101,13 @@ GQuark ev_document_error_quark (void);
GMutex *ev_document_get_doc_mutex (void);
void ev_document_doc_mutex_lock (void);
void ev_document_doc_mutex_unlock (void);
gboolean ev_document_doc_mutex_trylock(void);
/* FontConfig mutex */
GMutex *ev_document_get_fc_mutex (void);
void ev_document_fc_mutex_lock (void);
void ev_document_fc_mutex_unlock (void);
gboolean ev_document_fc_mutex_trylock (void);
EvDocumentInfo *ev_document_get_info (EvDocument *document);
gboolean ev_document_load (EvDocument *document,

View File

@ -28,8 +28,8 @@ evince_SOURCES= \
eggfindbar.h \
ev-application.c \
ev-application.h \
ev-job-queue.h \
ev-job-queue.c \
ev-job-scheduler.h \
ev-job-scheduler.c \
ev-jobs.h \
ev-jobs.c \
ev-file-monitor.h \

View File

@ -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;
}

305
shell/ev-job-scheduler.c Normal file
View File

@ -0,0 +1,305 @@
/* 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);
}
}

View File

@ -1,6 +1,7 @@
/* this file is part of evince, a gnome document viewer
/* ev-job-scheduler.h
* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2005 Red Hat, Inc
* 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
@ -17,23 +18,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __EV_JOB_QUEUE_H__
#define __EV_JOB_QUEUE_H__
#ifndef EV_JOB_SCHEDULER_H
#define EV_JOB_SCHEDULER_H
#include <gtk/gtk.h>
#include <glib.h>
#include "ev-jobs.h"
G_BEGIN_DECLS
typedef enum {
EV_JOB_PRIORITY_URGENT, /* Rendering current page range */
EV_JOB_PRIORITY_HIGH, /* Rendering current thumbnail range */
EV_JOB_PRIORITY_LOW, /* Rendering pages not in current range */
EV_JOB_PRIORITY_NONE, /* Any other job: load, save, print, ... */
EV_JOB_N_PRIORITIES
} EvJobPriority;
void ev_job_queue_init (void);
void ev_job_queue_add_job (EvJob *job,
EvJobPriority priority);
gboolean ev_job_queue_update_job (EvJob *job,
EvJobPriority new_priority);
gboolean ev_job_queue_remove_job (EvJob *job);
void ev_job_scheduler_push_job (EvJob *job,
EvJobPriority priority);
void ev_job_scheduler_update_job (EvJob *job,
EvJobPriority priority);
G_END_DECLS
#endif /* __EV_JOB_QUEUE_H__ */
#endif /* EV_JOB_SCHEDULER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
* Copyright (C) 2005 Red Hat, Inc
*
* Evince is free software; you can redistribute it and/or modify it
@ -55,6 +56,7 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB, EvJob))
#define EV_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB, EvJobClass))
#define EV_IS_JOB(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB))
#define EV_JOB_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_JOB, EvJobClass))
#define EV_TYPE_JOB_LINKS (ev_job_links_get_type())
#define EV_JOB_LINKS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_LINKS, EvJobLinks))
@ -92,23 +94,38 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_IS_JOB_PRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_PRINT))
typedef enum {
EV_JOB_PRIORITY_LOW,
EV_JOB_PRIORITY_HIGH,
} EvJobPriority;
EV_JOB_RUN_THREAD,
EV_JOB_RUN_MAIN_LOOP
} EvJobRunMode;
struct _EvJob
{
GObject parent;
EvDocument *document;
gboolean finished;
gboolean async;
EvJobRunMode run_mode;
guint cancelled : 1;
guint finished : 1;
guint failed : 1;
GError *error;
GCancellable *cancellable;
guint idle_finished_id;
guint idle_cancelled_id;
};
struct _EvJobClass
{
GObjectClass parent_class;
void (* finished) (EvJob *job);
gboolean (*run) (EvJob *job);
/* Signals */
void (* cancelled) (EvJob *job);
void (* finished) (EvJob *job);
};
struct _EvJobLinks
@ -194,6 +211,9 @@ struct _EvJobFonts
struct _EvJobFontsClass
{
EvJobClass parent_class;
/* Signals */
void (* updated) (EvJobFonts *job);
};
struct _EvJobLoad
@ -203,7 +223,6 @@ struct _EvJobLoad
EvLinkDest *dest;
EvWindowRunMode mode;
gchar *search_string;
GError *error;
gchar *uri;
};
@ -216,7 +235,6 @@ struct _EvJobSave
{
EvJob parent;
GError *error;
gchar *uri;
gchar *document_uri;
};
@ -230,7 +248,6 @@ struct _EvJobPrint
{
EvJob parent;
GError *error;
const gchar *format;
gchar *temp_file;
EvPrintRange *ranges;
@ -251,12 +268,26 @@ struct _EvJobPrintClass
/* Base job class */
GType ev_job_get_type (void) G_GNUC_CONST;
void ev_job_finished (EvJob *job);
gboolean ev_job_run (EvJob *job);
void ev_job_cancel (EvJob *job);
void ev_job_failed (EvJob *job,
GQuark domain,
gint code,
const gchar *format,
...);
void ev_job_failed_from_error (EvJob *job,
GError *error);
void ev_job_succeeded (EvJob *job);
gboolean ev_job_is_cancelled (EvJob *job);
gboolean ev_job_is_finished (EvJob *job);
gboolean ev_job_is_failed (EvJob *job);
EvJobRunMode ev_job_get_run_mode (EvJob *job);
void ev_job_set_run_mode (EvJob *job,
EvJobRunMode run_mode);
/* EvJobLinks */
GType ev_job_links_get_type (void) G_GNUC_CONST;
EvJob *ev_job_links_new (EvDocument *document);
void ev_job_links_run (EvJobLinks *thumbnail);
/* EvJobRender */
GType ev_job_render_get_type (void) G_GNUC_CONST;
@ -272,20 +303,15 @@ void ev_job_render_set_selection_info (EvJobRender *job,
EvSelectionStyle selection_style,
GdkColor *text,
GdkColor *base);
void ev_job_render_run (EvJobRender *thumbnail);
/* EvJobThumbnail */
GType ev_job_thumbnail_get_type (void) G_GNUC_CONST;
EvJob *ev_job_thumbnail_new (EvDocument *document,
gint page,
gint rotation,
gdouble scale);
void ev_job_thumbnail_run (EvJobThumbnail *thumbnail);
/* EvJobFonts */
GType ev_job_fonts_get_type (void) G_GNUC_CONST;
EvJob *ev_job_fonts_new (EvDocument *document);
void ev_job_fonts_run (EvJobFonts *fonts);
/* EvJobLoad */
GType ev_job_load_get_type (void) G_GNUC_CONST;
@ -295,14 +321,12 @@ EvJob *ev_job_load_new (const gchar *uri,
const gchar *search_string);
void ev_job_load_set_uri (EvJobLoad *load,
const gchar *uri);
void ev_job_load_run (EvJobLoad *load);
/* EvJobSave */
GType ev_job_save_get_type (void) G_GNUC_CONST;
EvJob *ev_job_save_new (EvDocument *document,
const gchar *uri,
const gchar *document_uri);
void ev_job_save_run (EvJobSave *save);
/* EvJobPrint */
GType ev_job_print_get_type (void) G_GNUC_CONST;
@ -317,7 +341,6 @@ EvJob *ev_job_print_new (EvDocument *document,
gint copies,
gdouble collate,
gdouble reverse);
void ev_job_print_run (EvJobPrint *print);
G_END_DECLS

View File

@ -1,6 +1,5 @@
#include <config.h>
#include "ev-page-cache.h"
#include "ev-job-queue.h"
#include "ev-document-thumbnails.h"
#include "ev-page.h"
#include <stdlib.h>

View File

@ -1,6 +1,6 @@
#include <config.h>
#include "ev-pixbuf-cache.h"
#include "ev-job-queue.h"
#include "ev-job-scheduler.h"
#include "ev-page-cache.h"
#include "ev-document-images.h"
#include "ev-document-forms.h"
@ -163,8 +163,8 @@ dispose_cache_job_info (CacheJobInfo *job_info,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
data);
ev_job_queue_remove_job (job_info->job);
g_object_unref (G_OBJECT (job_info->job));
ev_job_cancel (job_info->job);
g_object_unref (job_info->job);
job_info->job = NULL;
}
if (job_info->surface) {
@ -313,7 +313,7 @@ check_job_size_and_unref (EvPixbufCache *pixbuf_cache,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
pixbuf_cache);
ev_job_queue_remove_job (job_info->job);
ev_job_cancel (job_info->job);
g_object_unref (job_info->job);
job_info->job = NULL;
}
@ -330,11 +330,11 @@ move_one_job (CacheJobInfo *job_info,
CacheJobInfo *new_next_job,
int start_page,
int end_page,
EvJobPriority priority)
gint priority)
{
CacheJobInfo *target_page = NULL;
int page_offset;
EvJobPriority new_priority;
gint new_priority;
if (page < (start_page - pixbuf_cache->preload_cache_size) ||
page > (end_page + pixbuf_cache->preload_cache_size)) {
@ -361,7 +361,7 @@ move_one_job (CacheJobInfo *job_info,
page_offset = page - start_page;
g_assert (page_offset >= 0 &&
page_offset <= ((end_page - start_page) + 1));
new_priority = EV_JOB_PRIORITY_HIGH;
new_priority = EV_JOB_PRIORITY_URGENT;
target_page = new_job_list + page_offset;
}
@ -374,7 +374,7 @@ move_one_job (CacheJobInfo *job_info,
job_info->form_field_mapping = NULL;
if (new_priority != priority && target_page->job) {
ev_job_queue_update_job (target_page->job, new_priority);
ev_job_scheduler_update_job (target_page->job, new_priority);
}
}
@ -421,7 +421,7 @@ ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache,
move_one_job (pixbuf_cache->job_list + i,
pixbuf_cache, page,
new_job_list, new_prev_job, new_next_job,
start_page, end_page, EV_JOB_PRIORITY_HIGH);
start_page, end_page, EV_JOB_PRIORITY_URGENT);
page ++;
}
@ -529,8 +529,8 @@ copy_job_to_job_info (EvJobRender *job_render,
g_signal_handlers_disconnect_by_func (job_info->job,
G_CALLBACK (job_finished_cb),
pixbuf_cache);
ev_job_queue_remove_job (job_info->job);
g_object_unref (G_OBJECT (job_info->job));
ev_job_cancel (job_info->job);
g_object_unref (job_info->job);
job_info->job = NULL;
}
}
@ -647,13 +647,13 @@ add_job (EvPixbufCache *pixbuf_cache,
text, base);
}
ev_job_queue_add_job (job_info->job, priority);
g_signal_connect (G_OBJECT (job_info->job), "page-ready",
G_CALLBACK (job_page_ready_cb),
pixbuf_cache);
g_signal_connect (G_OBJECT (job_info->job), "finished",
G_CALLBACK (job_finished_cb),
pixbuf_cache);
ev_job_scheduler_push_job (job_info->job, priority);
}
static void
@ -701,7 +701,7 @@ ev_pixbuf_cache_add_jobs_if_needed (EvPixbufCache *pixbuf_cache,
add_job_if_needed (pixbuf_cache, job_info,
page_cache, page, rotation, scale,
EV_JOB_PRIORITY_HIGH);
EV_JOB_PRIORITY_URGENT);
}
for (i = FIRST_VISABLE_PREV(pixbuf_cache); i < pixbuf_cache->preload_cache_size; i++) {
@ -1235,7 +1235,7 @@ ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache,
add_job (pixbuf_cache, job_info, page_cache, region,
width, height, page, rotation, scale,
EV_JOB_PRIORITY_HIGH);
EV_JOB_PRIORITY_URGENT);
}

View File

@ -27,7 +27,6 @@
#include <gtk/gtkwidget.h>
#include "ev-document.h"
#include "ev-selection.h"
#include "ev-job-queue.h"
G_BEGIN_DECLS

View File

@ -25,7 +25,7 @@
#include "ev-properties-fonts.h"
#include "ev-document-fonts.h"
#include "ev-jobs.h"
#include "ev-job-queue.h"
#include "ev-job-scheduler.h"
#include <glib/gi18n.h>
#include <gtk/gtktreeview.h>
@ -63,12 +63,10 @@ ev_properties_fonts_dispose (GObject *object)
}
if (properties->fonts_job) {
g_signal_handlers_disconnect_by_func
(properties->fonts_job,
job_fonts_finished_cb,
properties);
ev_job_queue_remove_job (properties->fonts_job);
g_signal_handlers_disconnect_by_func (properties->fonts_job,
job_fonts_finished_cb,
properties);
ev_job_cancel (properties->fonts_job);
g_object_unref (properties->fonts_job);
properties->fonts_job = NULL;
@ -161,29 +159,23 @@ update_progress_label (GtkWidget *label, double progress)
static void
job_fonts_finished_cb (EvJob *job, EvPropertiesFonts *properties)
{
EvDocumentFonts *document_fonts = EV_DOCUMENT_FONTS (job->document);
double progress;
progress = ev_document_fonts_get_progress (document_fonts);
{
g_signal_handlers_disconnect_by_func (job, job_fonts_finished_cb, properties);
g_object_unref (properties->fonts_job);
properties->fonts_job = NULL;
}
static void
job_fonts_updated_cb (EvJobFonts *job, gdouble progress, EvPropertiesFonts *properties)
{
GtkTreeModel *model;
EvDocumentFonts *document_fonts = EV_DOCUMENT_FONTS (properties->document);
update_progress_label (properties->fonts_progress_label, progress);
if (EV_JOB_FONTS (job)->scan_completed) {
g_signal_handlers_disconnect_by_func
(job, job_fonts_finished_cb, properties);
g_object_unref (properties->fonts_job);
properties->fonts_job = NULL;
} else {
GtkTreeModel *model;
model = gtk_tree_view_get_model
(GTK_TREE_VIEW (properties->fonts_treeview));
ev_document_doc_mutex_lock ();
ev_document_fonts_fill_model (document_fonts, model);
ev_document_doc_mutex_unlock ();
ev_job_queue_add_job (job, EV_JOB_PRIORITY_LOW);
}
model = gtk_tree_view_get_model (GTK_TREE_VIEW (properties->fonts_treeview));
/* Documen lock is already held by the jop */
ev_document_fonts_fill_model (document_fonts, model);
}
void
@ -200,10 +192,13 @@ ev_properties_fonts_set_document (EvPropertiesFonts *properties,
gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store));
properties->fonts_job = ev_job_fonts_new (properties->document);
g_signal_connect (properties->fonts_job, "updated",
G_CALLBACK (job_fonts_updated_cb),
properties);
g_signal_connect (properties->fonts_job, "finished",
G_CALLBACK (job_fonts_finished_cb),
properties);
ev_job_queue_add_job (properties->fonts_job, EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (properties->fonts_job, EV_JOB_PRIORITY_NONE);
}
GtkWidget *

View File

@ -30,7 +30,7 @@
#include "ev-sidebar-page.h"
#include "ev-sidebar-links.h"
#include "ev-job-queue.h"
#include "ev-job-scheduler.h"
#include "ev-document-links.h"
#include "ev-window.h"
@ -145,7 +145,7 @@ ev_sidebar_links_dispose (GObject *object)
if (sidebar->priv->job) {
g_signal_handlers_disconnect_by_func (sidebar->priv->job,
job_finished_callback, sidebar);
ev_job_queue_remove_job (sidebar->priv->job);
ev_job_cancel (sidebar->priv->job);
g_object_unref (sidebar->priv->job);
sidebar->priv->job = NULL;
}
@ -702,7 +702,7 @@ ev_sidebar_links_set_document (EvSidebarPage *sidebar_page,
G_CALLBACK (job_finished_callback),
sidebar_links);
/* The priority doesn't matter for this job */
ev_job_queue_add_job (priv->job, EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
}
static gboolean

View File

@ -34,7 +34,7 @@
#include "ev-sidebar-thumbnails.h"
#include "ev-document-thumbnails.h"
#include "ev-document-misc.h"
#include "ev-job-queue.h"
#include "ev-job-scheduler.h"
#include "ev-window.h"
#include "ev-utils.h"
@ -207,7 +207,7 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
if (job) {
g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, sidebar_thumbnails);
ev_job_queue_remove_job (EV_JOB (job));
ev_job_cancel (EV_JOB (job));
g_object_unref (job);
}
@ -263,7 +263,7 @@ add_range (EvSidebarThumbnails *sidebar_thumbnails,
job = ev_job_thumbnail_new (priv->document,
page, priv->rotation,
get_scale_for_page (sidebar_thumbnails, page));
ev_job_queue_add_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
ev_job_scheduler_push_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
g_object_set_data_full (G_OBJECT (job), "tree_iter",
gtk_tree_iter_copy (&iter),
@ -688,8 +688,8 @@ ev_sidebar_thumbnails_set_document (EvSidebarPage *sidebar_page,
static gboolean
ev_sidebar_thumbnails_clear_job (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
EvJob *job;
@ -697,7 +697,7 @@ ev_sidebar_thumbnails_clear_job (GtkTreeModel *model,
gtk_tree_model_get (model, iter, COLUMN_JOB, &job, -1);
if (job != NULL) {
ev_job_queue_remove_job (job);
ev_job_cancel (job);
g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, data);
g_object_unref (job);
}

View File

@ -24,6 +24,7 @@
#include "ev-view.h"
#include "ev-pixbuf-cache.h"
#include "ev-page-cache.h"
#include "ev-jobs.h"
#include "ev-image.h"
#include "ev-form-field.h"
#include "ev-selection.h"

View File

@ -39,7 +39,6 @@
#include "ev-document-transition.h"
#include "ev-document-forms.h"
#include "ev-document-misc.h"
#include "ev-job-queue.h"
#include "ev-page-cache.h"
#include "ev-pixbuf-cache.h"
#include "ev-transition-animation.h"

View File

@ -49,7 +49,7 @@
#include "ev-document-images.h"
#include "ev-document-security.h"
#include "ev-document-factory.h"
#include "ev-job-queue.h"
#include "ev-job-scheduler.h"
#include "ev-jobs.h"
#include "ev-sidebar-page.h"
#include "eggfindbar.h"
@ -221,16 +221,16 @@ static void ev_window_sidebar_visibility_changed_cb (EvSidebar *ev_si
EvWindow *ev_window);
static void ev_window_set_page_mode (EvWindow *window,
EvWindowPageMode page_mode);
static void ev_window_load_job_cb (EvJobLoad *job,
static void ev_window_load_job_cb (EvJob *job,
gpointer data);
static void ev_window_reload_document (EvWindow *window);
static void ev_window_reload_job_cb (EvJobLoad *job,
static void ev_window_reload_job_cb (EvJob *job,
EvWindow *window);
static void ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
EvWindow *ev_window);
static void ev_window_print_job_cb (EvJobPrint *job,
static void ev_window_print_job_cb (EvJob *job,
EvWindow *window);
static void ev_window_save_job_cb (EvJobSave *save,
static void ev_window_save_job_cb (EvJob *save,
EvWindow *window);
static void ev_window_sizing_mode_changed_cb (EvView *view,
GParamSpec *pspec,
@ -1080,8 +1080,9 @@ static void
ev_window_clear_thumbnail_job (EvWindow *ev_window)
{
if (ev_window->priv->thumbnail_job != NULL) {
ev_job_queue_remove_job (ev_window->priv->thumbnail_job);
if (!ev_job_is_finished (ev_window->priv->thumbnail_job))
ev_job_cancel (ev_window->priv->thumbnail_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job,
ev_window_set_icon_from_thumbnail,
ev_window);
@ -1125,7 +1126,7 @@ ev_window_refresh_window_thumbnail (EvWindow *ev_window, int rotation)
g_signal_connect (ev_window->priv->thumbnail_job, "finished",
G_CALLBACK (ev_window_set_icon_from_thumbnail),
ev_window);
ev_job_queue_add_job (EV_JOB (ev_window->priv->thumbnail_job), EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE);
}
static gboolean
@ -1231,7 +1232,7 @@ password_dialog_response (GtkWidget *password_dialog,
ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog));
ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT);
ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
gtk_widget_destroy (password_dialog);
@ -1277,9 +1278,8 @@ static void
ev_window_clear_load_job (EvWindow *ev_window)
{
if (ev_window->priv->load_job != NULL) {
if (!ev_window->priv->load_job->finished)
ev_job_queue_remove_job (ev_window->priv->load_job);
if (!ev_job_is_finished (ev_window->priv->load_job))
ev_job_cancel (ev_window->priv->load_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
g_object_unref (ev_window->priv->load_job);
@ -1291,9 +1291,8 @@ static void
ev_window_clear_reload_job (EvWindow *ev_window)
{
if (ev_window->priv->reload_job != NULL) {
if (!ev_window->priv->reload_job->finished)
ev_job_queue_remove_job (ev_window->priv->reload_job);
if (!ev_job_is_finished (ev_window->priv->reload_job))
ev_job_cancel (ev_window->priv->reload_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
g_object_unref (ev_window->priv->reload_job);
@ -1349,21 +1348,22 @@ ev_window_clear_temp_file (EvWindow *ev_window)
* function should _not_ necessarily expect those to exist after being
* called. */
static void
ev_window_load_job_cb (EvJobLoad *job,
ev_window_load_job_cb (EvJob *job,
gpointer data)
{
EvWindow *ev_window = EV_WINDOW (data);
EvDocument *document = EV_JOB (job)->document;
EvJobLoad *job_load = EV_JOB_LOAD (job);
g_assert (job->uri);
g_assert (job_load->uri);
ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
/* Success! */
if (job->error == NULL) {
if (!ev_job_is_failed (job)) {
ev_window_set_document (ev_window, document);
if (job->mode != EV_WINDOW_MODE_PREVIEW) {
if (job_load->mode != EV_WINDOW_MODE_PREVIEW) {
setup_view_from_metadata (ev_window);
}
@ -1371,17 +1371,17 @@ ev_window_load_job_cb (EvJobLoad *job,
ev_window_add_recent (ev_window, ev_window->priv->uri);
}
if (job->dest) {
if (job_load->dest) {
EvLink *link;
EvLinkAction *link_action;
link_action = ev_link_action_new_dest (g_object_ref (job->dest));
link_action = ev_link_action_new_dest (g_object_ref (job_load->dest));
link = ev_link_new (NULL, link_action);
ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
g_object_unref (link);
}
switch (job->mode) {
switch (job_load->mode) {
case EV_WINDOW_MODE_FULLSCREEN:
ev_window_run_fullscreen (ev_window);
break;
@ -1395,14 +1395,23 @@ ev_window_load_job_cb (EvJobLoad *job,
break;
}
if (job->search_string && EV_IS_DOCUMENT_FIND (document)) {
/* Restart the search after reloading */
if (ev_window->priv->in_reload) {
GtkWidget *widget;
widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
NULL, ev_window);
}
} else if (job_load->search_string && EV_IS_DOCUMENT_FIND (document)) {
ev_window_cmd_edit_find (NULL, ev_window);
egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
job->search_string);
job_load->search_string);
}
/* Create a monitor for the document */
ev_window->priv->monitor = ev_file_monitor_new (job->uri);
ev_window->priv->monitor = ev_file_monitor_new (job_load->uri);
g_signal_connect_swapped (G_OBJECT (ev_window->priv->monitor), "changed",
G_CALLBACK (ev_window_document_changed),
ev_window);
@ -1418,7 +1427,7 @@ ev_window_load_job_cb (EvJobLoad *job,
setup_view_from_metadata (ev_window);
file = g_file_new_for_uri (job->uri);
file = g_file_new_for_uri (job_load->uri);
base_name = g_file_get_basename (file);
ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
base_name);
@ -1436,18 +1445,18 @@ ev_window_load_job_cb (EvJobLoad *job,
}
static void
ev_window_reload_job_cb (EvJobLoad *job,
EvWindow *ev_window)
ev_window_reload_job_cb (EvJob *job,
EvWindow *ev_window)
{
GtkWidget *widget;
if (job->error) {
if (ev_job_is_failed (job)) {
ev_window_clear_reload_job (ev_window);
ev_window->priv->in_reload = FALSE;
return;
}
ev_window_set_document (ev_window, EV_JOB (job)->document);
ev_window_set_document (ev_window, job->document);
/* Restart the search after reloading */
widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
@ -1539,7 +1548,7 @@ window_open_file_copy_ready_cb (GFile *source,
g_file_copy_finish (source, async_result, &error);
if (!error) {
ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
g_object_unref (source);
return;
@ -1649,7 +1658,7 @@ ev_window_open_uri (EvWindow *ev_window,
ev_window_load_file_remote (ev_window, source_file);
} else {
g_object_unref (source_file);
ev_job_queue_add_job (ev_window->priv->load_job, EV_JOB_PRIORITY_HIGH);
ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
}
}
@ -1666,7 +1675,7 @@ ev_window_reload_document (EvWindow *ev_window)
g_signal_connect (ev_window->priv->reload_job, "finished",
G_CALLBACK (ev_window_reload_job_cb),
ev_window);
ev_job_queue_add_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE);
}
static void
@ -2067,8 +2076,8 @@ static void
ev_window_clear_save_job (EvWindow *ev_window)
{
if (ev_window->priv->save_job != NULL) {
if (!ev_window->priv->save_job->finished)
ev_job_queue_remove_job (ev_window->priv->save_job);
if (!ev_job_is_finished (ev_window->priv->save_job))
ev_job_cancel (ev_window->priv->save_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->save_job,
ev_window_save_job_cb,
@ -2079,13 +2088,14 @@ ev_window_clear_save_job (EvWindow *ev_window)
}
static void
ev_window_save_job_cb (EvJobSave *job,
ev_window_save_job_cb (EvJob *job,
EvWindow *window)
{
if (job->error) {
if (ev_job_is_failed (job)) {
gchar *msg;
msg = g_strdup_printf (_("The file could not be saved as “%s”."), job->uri);
msg = g_strdup_printf (_("The file could not be saved as “%s”."),
EV_JOB_SAVE (job)->uri);
ev_window_error_message (GTK_WINDOW (window), msg, job->error);
g_free (msg);
}
@ -2114,10 +2124,9 @@ file_save_dialog_response_cb (GtkWidget *fc,
G_CALLBACK (ev_window_save_job_cb),
ev_window);
/* The priority doesn't matter for this job */
ev_job_queue_add_job (ev_window->priv->save_job, EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (ev_window->priv->save_job, EV_JOB_PRIORITY_NONE);
g_free (uri);
gtk_widget_destroy (fc);
}
@ -2187,8 +2196,8 @@ static void
ev_window_clear_print_job (EvWindow *window)
{
if (window->priv->print_job) {
if (!window->priv->print_job->finished)
ev_job_queue_remove_job (window->priv->print_job);
if (!ev_job_is_finished (window->priv->print_job))
ev_job_cancel (window->priv->print_job);
g_signal_handlers_disconnect_by_func (window->priv->print_job,
ev_window_print_job_cb,
@ -2349,18 +2358,18 @@ ev_window_print_send (EvWindow *window,
}
static void
ev_window_print_job_cb (EvJobPrint *job,
EvWindow *window)
ev_window_print_job_cb (EvJob *job,
EvWindow *window)
{
if (job->error) {
if (ev_job_is_failed (job)) {
g_warning ("%s", job->error->message);
ev_window_clear_print_job (window);
return;
}
g_assert (job->temp_file != NULL);
g_assert (EV_JOB_PRINT (job)->temp_file != NULL);
ev_window_print_send (window, job->temp_file);
ev_window_print_send (window, EV_JOB_PRINT (job)->temp_file);
}
static gboolean
@ -2494,7 +2503,7 @@ ev_window_print_dialog_response_cb (GtkDialog *dialog,
G_CALLBACK (ev_window_print_job_cb),
window);
/* The priority doesn't matter for this job */
ev_job_queue_add_job (window->priv->print_job, EV_JOB_PRIORITY_LOW);
ev_job_scheduler_push_job (window->priv->print_job, EV_JOB_PRIORITY_NONE);
gtk_widget_destroy (GTK_WIDGET (dialog));
window->priv->print_dialog = NULL;

View File

@ -41,7 +41,6 @@
#endif
#include "ev-stock-icons.h"
#include "ev-job-queue.h"
#include "ev-file-helpers.h"
#include "ev-backends-manager.h"
@ -391,7 +390,6 @@ main (int argc, char *argv[])
ev_metadata_manager_init ();
}
ev_job_queue_init ();
g_set_application_name (_("Evince Document Viewer"));
ev_file_helpers_init ();