ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/gnome-vfs2-2.3.8-1.src.rpm
[gnome-vfs-httpcaptive.git] / libgnomevfs / gnome-vfs-job-slave.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gnome-vfs-job-slave.c - Thread for asynchronous GnomeVFSJobs
3    (version for POSIX threads).
4
5    Copyright (C) 1999 Free Software Foundation
6
7    The Gnome Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The Gnome Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.
21
22    Author: Ettore Perazzoli <ettore@comm2000.it> */
23
24 #include <config.h>
25 #include "gnome-vfs-job-slave.h"
26
27 #include "gnome-vfs-async-job-map.h"
28 #include "gnome-vfs-thread-pool.h"
29 #include "gnome-vfs-job-queue.h"
30 #include <glib/gmessages.h>
31 #include <unistd.h>
32
33 static volatile gboolean gnome_vfs_quitting = FALSE;
34 static volatile gboolean gnome_vfs_done_quitting = FALSE;
35
36
37 static void *
38 thread_routine (void *data)
39 {
40         guint id;
41         GnomeVFSJob *job;
42         GnomeVFSAsyncHandle *job_handle;
43         gboolean complete;
44
45         job_handle = (GnomeVFSAsyncHandle *) data;
46
47         id = GPOINTER_TO_UINT (job_handle);
48         /* job map must always be locked before the job_lock
49          * if both locks are needed */
50         _gnome_vfs_async_job_map_lock ();
51         
52         job = _gnome_vfs_async_job_map_get_job (job_handle);
53         
54         if (job == NULL) {
55                 JOB_DEBUG (("job already dead, bail %u", id));
56                 _gnome_vfs_async_job_map_unlock ();
57                 return NULL;
58         }
59         
60         JOB_DEBUG (("locking job_lock %u", id));
61         g_mutex_lock (job->job_lock);
62         _gnome_vfs_async_job_map_unlock ();
63
64         _gnome_vfs_job_execute (job);
65         complete = _gnome_vfs_job_complete (job);
66         
67         JOB_DEBUG (("Unlocking access lock %u", id));
68         g_mutex_unlock (job->job_lock);
69
70         if (complete) {
71                 _gnome_vfs_async_job_map_lock ();
72                 JOB_DEBUG (("job %u done, removing from map and destroying", id));
73                 _gnome_vfs_async_job_completed (job_handle);
74                 _gnome_vfs_job_destroy (job);
75                 _gnome_vfs_async_job_map_unlock ();
76         }
77
78         return NULL;
79 }
80
81 gboolean
82 _gnome_vfs_job_create_slave (GnomeVFSJob *job)
83 {
84         g_return_val_if_fail (job != NULL, FALSE);
85
86         if (gnome_vfs_quitting) {
87                 g_warning ("Someone still starting up GnomeVFS async calls after quit.");
88         }
89
90         if (gnome_vfs_done_quitting) {
91                 /* The application is quitting, we have already returned from
92                  * gnome_vfs_wait_for_slave_threads, we can't start any more threads
93                  * because they would potentially block indefinitely and prevent the
94                  * app from quitting.
95                  */
96                 return FALSE;
97         }
98         
99         if (_gnome_vfs_thread_create (thread_routine, job->job_handle) != 0) {
100                 g_warning ("Impossible to allocate a new GnomeVFSJob thread.");
101                 
102                 /* thread did not start up, remove the job from the hash table */
103                 _gnome_vfs_async_job_completed (job->job_handle);
104                 _gnome_vfs_job_destroy (job);
105                 return FALSE;
106         }
107
108         return TRUE;
109 }
110
111 void
112 _gnome_vfs_thread_backend_shutdown (void)
113 {
114         gboolean done;
115         int count;
116         
117         done = FALSE;
118
119         gnome_vfs_quitting = TRUE;
120
121         JOB_DEBUG (("###### shutting down"));
122
123         _gnome_vfs_job_queue_shutdown();
124
125         for (count = 0; ; count++) {
126                 /* Check if it is OK to quit. Originally we used a
127                  * count of slave threads, but now we use a count of
128                  * outstanding jobs instead to make sure that the job
129                  * is cleanly destroyed.
130                  */
131                 if (gnome_vfs_job_get_count () == 0) {
132                         done = TRUE;
133                         gnome_vfs_done_quitting = TRUE;
134                 }
135
136                 if (done) {
137                         break;
138                 }
139
140                 /* Some threads are still trying to quit, wait a bit until they
141                  * are done.
142                  */
143                 g_main_context_iteration (NULL, FALSE);
144                 usleep (20000);
145         }
146
147         _gnome_vfs_thread_pool_shutdown ();
148         _gnome_vfs_async_job_map_shutdown ();
149 }