]> www.fi.muni.cz Git - evince.git/blob - backend/ev-job-queue.c
Hungarian translation added by "Last-Translator: \n".
[evince.git] / backend / ev-job-queue.c
1 #include "ev-job-queue.h"
2
3 /* Like glib calling convention, all functions with _locked in their name assume
4  * that we've already locked the doc mutex and can freely and safely access
5  * data.
6  */
7 GCond *render_cond = NULL;
8 GMutex *ev_queue_mutex = NULL;
9
10 static GQueue *links_queue = NULL;
11 static GQueue *render_queue_high = NULL;
12 static GQueue *render_queue_low = NULL;
13 static GQueue *thumbnail_queue_high = NULL;
14 static GQueue *thumbnail_queue_low = NULL;
15
16 static gboolean
17 remove_job_from_queue_locked (GQueue *queue, EvJob *job)
18 {
19         GList *list;
20
21         list = g_queue_find (queue, job);
22         if (list) {
23                 g_object_unref (G_OBJECT (job));
24                 g_queue_delete_link (queue, list);
25
26                 return TRUE;
27         }
28         return FALSE;
29 }
30
31 static void
32 add_job_to_queue_locked (GQueue *queue,
33                          EvJob  *job)
34 {
35         g_object_ref (job);
36         g_queue_push_tail (queue, job);
37         g_cond_broadcast (render_cond);
38 }
39
40
41 static gboolean
42 notify_finished (GObject *job)
43 {
44         ev_job_finished (EV_JOB (job));
45
46         return FALSE;
47 }
48
49
50 static void
51 handle_job (EvJob *job)
52 {
53         g_object_ref (G_OBJECT (job));
54
55         if (EV_IS_JOB_THUMBNAIL (job))
56                 ev_job_thumbnail_run (EV_JOB_THUMBNAIL (job));
57         else if (EV_IS_JOB_LINKS (job))
58                 ev_job_links_run (EV_JOB_LINKS (job));
59         else if (EV_IS_JOB_RENDER (job))
60                 ev_job_render_run (EV_JOB_RENDER (job));
61
62         /* We let the idle own a ref, as we (the queue) are done with the job. */
63         g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
64                          (GSourceFunc) notify_finished,
65                          job,
66                          g_object_unref);
67 }
68
69 static EvJob *
70 search_for_jobs_unlocked (void)
71 {
72         EvJob *job;
73
74         job = (EvJob *) g_queue_pop_head (render_queue_high);
75         if (job)
76                 return job;
77
78         job = (EvJob *) g_queue_pop_head (thumbnail_queue_high);
79         if (job)
80                 return job;
81
82         job = (EvJob *) g_queue_pop_head (render_queue_low);
83         if (job)
84                 return job;
85
86         job = (EvJob *) g_queue_pop_head (links_queue);
87         if (job)
88                 return job;
89
90         job = (EvJob *) g_queue_pop_head (thumbnail_queue_low);
91         if (job)
92                 return job;
93
94         return NULL;
95 }
96
97 static gboolean
98 no_jobs_available_unlocked (void)
99 {
100         return g_queue_is_empty (render_queue_high)
101                 && g_queue_is_empty (render_queue_low)
102                 && g_queue_is_empty (links_queue)
103                 && g_queue_is_empty (thumbnail_queue_high)
104                 && g_queue_is_empty (thumbnail_queue_low);
105 }
106
107 /* the thread mainloop function */
108 static gpointer
109 ev_render_thread (gpointer data)
110 {
111         while (TRUE) {
112                 EvJob *job;
113
114                 g_mutex_lock (ev_queue_mutex);
115                 if (no_jobs_available_unlocked ()) {
116                         g_cond_wait (render_cond, ev_queue_mutex);
117                 }
118
119                 job = search_for_jobs_unlocked ();
120                 g_mutex_unlock (ev_queue_mutex);
121
122                 /* Now that we have our job, we handle it */
123                 if (job) {
124                         handle_job (job);
125                         g_object_unref (G_OBJECT (job));
126                 }
127         }
128         return NULL;
129
130 }
131
132 /* Public Functions */
133 void
134 ev_job_queue_init (void)
135 {
136         if (!g_thread_supported ()) g_thread_init (NULL);
137
138         render_cond = g_cond_new ();
139         ev_queue_mutex = g_mutex_new ();
140
141         links_queue = g_queue_new ();
142         render_queue_high = g_queue_new ();
143         render_queue_low = g_queue_new ();
144         thumbnail_queue_high = g_queue_new ();
145         thumbnail_queue_low = g_queue_new ();
146
147         g_thread_create (ev_render_thread, NULL, FALSE, NULL);
148
149 }
150
151 static GQueue *
152 find_queue (EvJob         *job,
153             EvJobPriority  priority)
154 {
155         if (EV_IS_JOB_RENDER (job)) {
156                 if (priority == EV_JOB_PRIORITY_HIGH)
157                         return render_queue_high;
158                 else
159                         return render_queue_low;
160         } else if (EV_IS_JOB_THUMBNAIL (job)) {
161                 if (priority == EV_JOB_PRIORITY_HIGH)
162                         return thumbnail_queue_high;
163                 else
164                         return thumbnail_queue_low;
165         } else if (EV_IS_JOB_LINKS (job)) {
166                 /* the priority doesn't effect links */
167                 return links_queue;
168         }
169
170         g_assert_not_reached ();
171         return NULL;
172 }
173
174 void
175 ev_job_queue_add_job (EvJob         *job,
176                       EvJobPriority  priority)
177 {
178         GQueue *queue;
179
180         g_return_if_fail (EV_IS_JOB (job));
181
182         queue = find_queue (job, priority);
183
184         g_mutex_lock (ev_queue_mutex);
185         add_job_to_queue_locked (queue, job);
186         g_mutex_unlock (ev_queue_mutex);
187 }
188
189 gboolean
190 ev_job_queue_update_job (EvJob         *job,
191                          EvJobPriority  new_priority)
192 {
193         gboolean retval = FALSE;
194         
195         g_return_val_if_fail (EV_IS_JOB (job), FALSE);
196
197         g_mutex_lock (ev_queue_mutex);
198         g_object_ref (job);
199         
200         if (EV_IS_JOB_THUMBNAIL (job)) {
201                 if (new_priority == EV_JOB_PRIORITY_LOW) {
202                         if (remove_job_from_queue_locked (thumbnail_queue_high, job)) {
203                                 add_job_to_queue_locked (thumbnail_queue_low, job);
204                                 retval = TRUE;
205                         }
206                 } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
207                         if (remove_job_from_queue_locked (thumbnail_queue_low, job)) {
208                                 add_job_to_queue_locked (thumbnail_queue_high, job);
209                                 retval = TRUE;
210                         }
211                 }
212         } else if (EV_IS_JOB_RENDER (job)) {
213                 if (new_priority == EV_JOB_PRIORITY_LOW) {
214                         if (remove_job_from_queue_locked (render_queue_high, job)) {
215                                 add_job_to_queue_locked (render_queue_low, job);
216                                 retval = TRUE;
217                         }
218                 } else if (new_priority == EV_JOB_PRIORITY_HIGH) {
219                         if (remove_job_from_queue_locked (render_queue_low, job)) {
220                                 add_job_to_queue_locked (render_queue_high, job);
221                                 retval = TRUE;
222                         }
223                 }
224         } else {
225                 /* We don't have a priority queue for any of the other jobs */
226         }
227         g_object_unref (job);
228         g_mutex_unlock (ev_queue_mutex);
229
230         return retval;
231 }
232
233 gboolean
234 ev_job_queue_remove_job (EvJob *job)
235 {
236         gboolean retval = FALSE;
237
238         g_return_val_if_fail (EV_IS_JOB (job), FALSE);
239
240         g_mutex_lock (ev_queue_mutex);
241
242         if (EV_IS_JOB_THUMBNAIL (job)) {
243                 retval = remove_job_from_queue_locked (thumbnail_queue_high, job);
244                 retval = retval || remove_job_from_queue_locked (thumbnail_queue_low, job);
245         } else if (EV_IS_JOB_RENDER (job)) {
246                 retval = remove_job_from_queue_locked (render_queue_high, job);
247                 retval = retval || remove_job_from_queue_locked (render_queue_low, job);
248         } else if (EV_IS_JOB_LINKS (job)) {
249                 retval = remove_job_from_queue_locked (links_queue, job);
250         } else {
251                 g_assert_not_reached ();
252         }
253         
254         g_mutex_unlock (ev_queue_mutex);
255
256         return retval;
257 }
258
259