Include "config.h" instead of <config.h> Command used: find -name
[platform/upstream/glib.git] / gio / gcancellable.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include "config.h"
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #include <fcntl.h>
28 #include <gioerror.h>
29 #ifdef G_OS_WIN32
30 #include <io.h>
31 #ifndef pipe
32 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
33 #endif
34 #endif
35 #include "gcancellable.h"
36 #include "glibintl.h"
37
38 #include "gioalias.h"
39
40 /**
41  * SECTION:gcancellable
42  * @short_description: Thread-safe Operation Cancellation Stack
43  * @include: gio/gio.h
44  *
45  * GCancellable is a thread-safe operation cancellation stack used 
46  * throughout GIO to allow for cancellation of synchronous and
47  * asynchronous operations.
48  */
49
50 enum {
51   CANCELLED,
52   LAST_SIGNAL
53 };
54
55 struct _GCancellable
56 {
57   GObject parent_instance;
58
59   guint cancelled : 1;
60   guint allocated_pipe : 1;
61   int cancel_pipe[2];
62 };
63
64 static guint signals[LAST_SIGNAL] = { 0 };
65
66 G_DEFINE_TYPE (GCancellable, g_cancellable, G_TYPE_OBJECT);
67
68 static GStaticPrivate current_cancellable = G_STATIC_PRIVATE_INIT;
69 G_LOCK_DEFINE_STATIC(cancellable);
70   
71 static void
72 g_cancellable_finalize (GObject *object)
73 {
74   GCancellable *cancellable = G_CANCELLABLE (object);
75
76   if (cancellable->cancel_pipe[0] != -1)
77     close (cancellable->cancel_pipe[0]);
78   
79   if (cancellable->cancel_pipe[1] != -1)
80     close (cancellable->cancel_pipe[1]);
81
82   G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
83 }
84
85 static void
86 g_cancellable_class_init (GCancellableClass *klass)
87 {
88   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
89   
90   gobject_class->finalize = g_cancellable_finalize;
91
92   /**
93    * GCancellable::cancelled:
94    * @cancellable: a #GCancellable.
95    * 
96    * Emitted when the operation has been cancelled from another thread.
97    * 
98    * Can be used by implementations of cancellable operations. This will
99    * be emitted in the thread that tried to cancel the operation, not the
100    * thread the is running the operation.
101    */
102   signals[CANCELLED] =
103     g_signal_new (I_("cancelled"),
104                   G_TYPE_FROM_CLASS (gobject_class),
105                   G_SIGNAL_RUN_LAST,
106                   G_STRUCT_OFFSET (GCancellableClass, cancelled),
107                   NULL, NULL,
108                   g_cclosure_marshal_VOID__VOID,
109                   G_TYPE_NONE, 0);
110   
111 }
112
113 static void
114 set_fd_nonblocking (int fd)
115 {
116 #ifdef F_GETFL
117   glong fcntl_flags;
118   fcntl_flags = fcntl (fd, F_GETFL);
119
120 #ifdef O_NONBLOCK
121   fcntl_flags |= O_NONBLOCK;
122 #else
123   fcntl_flags |= O_NDELAY;
124 #endif
125
126   fcntl (fd, F_SETFL, fcntl_flags);
127 #endif
128 }
129
130 static void
131 g_cancellable_open_pipe (GCancellable *cancellable)
132 {
133   if (pipe (cancellable->cancel_pipe) == 0)
134     {
135       /* Make them nonblocking, just to be sure we don't block
136        * on errors and stuff
137        */
138       set_fd_nonblocking (cancellable->cancel_pipe[0]);
139       set_fd_nonblocking (cancellable->cancel_pipe[1]);
140     }
141   else
142     g_warning ("Failed to create pipe for GCancellable. Out of file descriptors?");
143 }
144
145 static void
146 g_cancellable_init (GCancellable *cancellable)
147 {
148   cancellable->cancel_pipe[0] = -1;
149   cancellable->cancel_pipe[1] = -1;
150 }
151
152 /**
153  * g_cancellable_new:
154  * 
155  * Creates a new #GCancellable object.
156  *
157  * Applications that want to start one or more operations
158  * that should be cancellable should create a #GCancellable
159  * and pass it to the operations.
160  *
161  * One #GCancellable can be used in multiple consecutive
162  * operations, but not in multiple concurrent operations.
163  *  
164  * Returns: a #GCancellable.
165  **/
166 GCancellable *
167 g_cancellable_new (void)
168 {
169   return g_object_new (G_TYPE_CANCELLABLE, NULL);
170 }
171
172 /**
173  * g_cancellable_push_current:
174  * @cancellable: optional #GCancellable object, %NULL to ignore.
175  * 
176  * Pushes @cancellable onto the cancellable stack. The current
177  * cancllable can then be recieved using g_cancellable_get_current().
178  *
179  * This is useful when implementing cancellable operations in
180  * code that does not allow you to pass down the cancellable object.
181  *
182  * This is typically called automatically by e.g. #GFile operations,
183  * so you rarely have to call this yourself.
184  **/
185 void
186 g_cancellable_push_current (GCancellable *cancellable)
187 {
188   GSList *l;
189
190   g_return_if_fail (cancellable != NULL);
191   
192   l = g_static_private_get (&current_cancellable);
193   l = g_slist_prepend (l, cancellable);
194   g_static_private_set (&current_cancellable, l, NULL);
195 }
196
197 /**
198  * g_cancellable_pop_current:
199  * @cancellable: optional #GCancellable object, %NULL to ignore.
200  *
201  * Pops @cancellable off the cancellable stack (verifying that @cancellable 
202  * is on the top of the stack).
203  **/
204 void
205 g_cancellable_pop_current (GCancellable *cancellable)
206 {
207   GSList *l;
208   
209   l = g_static_private_get (&current_cancellable);
210   
211   g_return_if_fail (l != NULL);
212   g_return_if_fail (l->data == cancellable);
213
214   l = g_slist_delete_link (l, l);
215   g_static_private_set (&current_cancellable, l, NULL);
216 }
217
218 /**
219  * g_cancellable_get_current:
220  * 
221  * Gets the top cancellable from the stack.
222  * 
223  * Returns: a #GCancellable from the top of the stack, or %NULL
224  * if the stack is empty. 
225  **/
226 GCancellable *
227 g_cancellable_get_current  (void)
228 {
229   GSList *l;
230   
231   l = g_static_private_get (&current_cancellable);
232   if (l == NULL)
233     return NULL;
234
235   return G_CANCELLABLE (l->data);
236 }
237
238 /**
239  * g_cancellable_reset:
240  * @cancellable: a #GCancellable object.
241  * 
242  * Resets @cancellable to its uncancelled state. 
243  **/
244 void 
245 g_cancellable_reset (GCancellable *cancellable)
246 {
247   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
248
249   G_LOCK(cancellable);
250   /* Make sure we're not leaving old cancel state around */
251   if (cancellable->cancelled)
252     {
253       char ch;
254       if (cancellable->cancel_pipe[0] != -1)
255         read (cancellable->cancel_pipe[0], &ch, 1);
256       cancellable->cancelled = FALSE;
257     }
258   G_UNLOCK(cancellable);
259 }
260
261 /**
262  * g_cancellable_is_cancelled:
263  * @cancellable: a #GCancellable or NULL.
264  * 
265  * Checks if a cancellable job has been cancelled.
266  * 
267  * Returns: %TRUE if @cancellable is cancelled, 
268  * FALSE if called with %NULL or if item is not cancelled. 
269  **/
270 gboolean
271 g_cancellable_is_cancelled (GCancellable *cancellable)
272 {
273   return cancellable != NULL && cancellable->cancelled;
274 }
275
276 /**
277  * g_cancellable_set_error_if_cancelled:
278  * @cancellable: a #GCancellable object.
279  * @error: #GError to append error state to.
280  * 
281  * If the @cancelalble is cancelled, sets the error to notify
282  * that the operation was cancelled.
283  * 
284  * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not.
285  **/
286 gboolean
287 g_cancellable_set_error_if_cancelled (GCancellable  *cancellable,
288                                       GError       **error)
289 {
290   if (g_cancellable_is_cancelled (cancellable))
291     {
292       g_set_error_literal (error,
293                            G_IO_ERROR,
294                            G_IO_ERROR_CANCELLED,
295                            _("Operation was cancelled"));
296       return TRUE;
297     }
298   
299   return FALSE;
300 }
301
302 /**
303  * g_cancellable_get_fd:
304  * @cancellable: a #GCancellable.
305  * 
306  * Gets the file descriptor for a cancellable job. This can be used to
307  * implement cancellable operations on Unix systems. The returned fd will
308  * turn readable when @cancellable is cancelled.
309  * 
310  * Returns: A valid file descriptor. %-1 if the file descriptor 
311  * is not supported, or on errors. 
312  **/
313 int
314 g_cancellable_get_fd (GCancellable *cancellable)
315 {
316   int fd;
317   if (cancellable == NULL)
318     return -1;
319   
320   G_LOCK(cancellable);
321   if (!cancellable->allocated_pipe)
322     {
323       cancellable->allocated_pipe = TRUE;
324       g_cancellable_open_pipe (cancellable);
325     }
326   
327   fd = cancellable->cancel_pipe[0];
328   G_UNLOCK(cancellable);
329   
330   return fd;
331 }
332
333 /**
334  * g_cancellable_cancel:
335  * @cancellable: a #GCancellable object.
336  * 
337  * Will set @cancellable to cancelled, and will emit the CANCELLED
338  * signal.
339  *
340  * This function is thread-safe. In other words, you can safely call it from
341  * another thread than the one running an operation that was passed
342  * the @cancellable.
343  **/
344 void
345 g_cancellable_cancel (GCancellable *cancellable)
346 {
347   gboolean cancel;
348
349   cancel = FALSE;
350   
351   G_LOCK(cancellable);
352   if (cancellable != NULL &&
353       !cancellable->cancelled)
354     {
355       char ch = 'x';
356       cancel = TRUE;
357       cancellable->cancelled = TRUE;
358       if (cancellable->cancel_pipe[1] != -1)
359         write (cancellable->cancel_pipe[1], &ch, 1);
360     }
361   G_UNLOCK(cancellable);
362
363   if (cancel)
364     {
365       g_object_ref (cancellable);
366       g_signal_emit (cancellable, signals[CANCELLED], 0);
367       g_object_unref (cancellable);
368     }
369 }
370
371 #define __G_CANCELLABLE_C__
372 #include "gioaliasdef.c"