Doc fixes
[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   if (G_OBJECT_CLASS (g_cancellable_parent_class)->finalize)
83     (*G_OBJECT_CLASS (g_cancellable_parent_class)->finalize) (object);
84 }
85
86 static void
87 g_cancellable_class_init (GCancellableClass *klass)
88 {
89   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90   
91   gobject_class->finalize = g_cancellable_finalize;
92
93   /**
94    * GCancellable::cancelled:
95    * @cancellable: a #GCancellable.
96    * 
97    * Emitted when the operation has been cancelled from another thread.
98    * 
99    * Can be used by implementations of cancellable operations. This will
100    * be emitted in the thread that tried to cancel the operation, not the
101    * thread the is running the operation.
102    */
103   signals[CANCELLED] =
104     g_signal_new (I_("cancelled"),
105                   G_TYPE_FROM_CLASS (gobject_class),
106                   G_SIGNAL_RUN_LAST,
107                   G_STRUCT_OFFSET (GCancellableClass, cancelled),
108                   NULL, NULL,
109                   g_cclosure_marshal_VOID__VOID,
110                   G_TYPE_NONE, 0);
111   
112 }
113
114 static void
115 set_fd_nonblocking (int fd)
116 {
117 #ifdef F_GETFL
118   glong fcntl_flags;
119   fcntl_flags = fcntl (fd, F_GETFL);
120
121 #ifdef O_NONBLOCK
122   fcntl_flags |= O_NONBLOCK;
123 #else
124   fcntl_flags |= O_NDELAY;
125 #endif
126
127   fcntl (fd, F_SETFL, fcntl_flags);
128 #endif
129 }
130
131 static void
132 g_cancellable_open_pipe (GCancellable *cancellable)
133 {
134   if (pipe (cancellable->cancel_pipe) == 0)
135     {
136       /* Make them nonblocking, just to be sure we don't block
137        * on errors and stuff
138        */
139       set_fd_nonblocking (cancellable->cancel_pipe[0]);
140       set_fd_nonblocking (cancellable->cancel_pipe[1]);
141     }
142   else
143     g_warning ("Failed to create pipe for GCancellable. Out of file descriptors?");
144 }
145
146 static void
147 g_cancellable_init (GCancellable *cancellable)
148 {
149   cancellable->cancel_pipe[0] = -1;
150   cancellable->cancel_pipe[1] = -1;
151 }
152
153 /**
154  * g_cancellable_new:
155  * 
156  * Creates a new #GCancellable object.
157  *
158  * Applications that want to start one or more operations
159  * that should be cancellable should create a #GCancellable
160  * and pass it to the operations.
161  *
162  * One #GCancellable can be used in multiple consecutive
163  * operations, but not in multiple concurrent operations.
164  *  
165  * Returns: a #GCancellable.
166  **/
167 GCancellable *
168 g_cancellable_new (void)
169 {
170   return g_object_new (G_TYPE_CANCELLABLE, NULL);
171 }
172
173 /**
174  * g_cancellable_push_current:
175  * @cancellable: optional #GCancellable object, %NULL to ignore.
176  * 
177  * Pushes @cancellable onto the cancellable stack. The current
178  * cancllable can then be recieved using g_cancellable_get_current().
179  *
180  * This is useful when implementing cancellable operations in
181  * code that does not allow you to pass down the cancellable object.
182  *
183  * This is typically called automatically by e.g. #GFile operations,
184  * so you rarely have to call this yourself.
185  **/
186 void
187 g_cancellable_push_current (GCancellable *cancellable)
188 {
189   GSList *l;
190
191   g_return_if_fail (cancellable != NULL);
192   
193   l = g_static_private_get (&current_cancellable);
194   l = g_slist_prepend (l, cancellable);
195   g_static_private_set (&current_cancellable, l, NULL);
196 }
197
198 /**
199  * g_cancellable_pop_current:
200  * @cancellable: optional #GCancellable object, %NULL to ignore.
201  *
202  * Pops @cancellable off the cancellable stack (verifying that @cancellable 
203  * is on the top of the stack).
204  **/
205 void
206 g_cancellable_pop_current (GCancellable *cancellable)
207 {
208   GSList *l;
209   
210   l = g_static_private_get (&current_cancellable);
211   
212   g_return_if_fail (l != NULL);
213   g_return_if_fail (l->data == cancellable);
214
215   l = g_slist_delete_link (l, l);
216   g_static_private_set (&current_cancellable, l, NULL);
217 }
218
219 /**
220  * g_cancellable_get_current:
221  * 
222  * Gets the top cancellable from the stack.
223  * 
224  * Returns: a #GCancellable from the top of the stack, or %NULL
225  * if the stack is empty. 
226  **/
227 GCancellable *
228 g_cancellable_get_current  (void)
229 {
230   GSList *l;
231   
232   l = g_static_private_get (&current_cancellable);
233   if (l == NULL)
234     return NULL;
235
236   return G_CANCELLABLE (l->data);
237 }
238
239 /**
240  * g_cancellable_reset:
241  * @cancellable: a #GCancellable object.
242  * 
243  * Resets @cancellable to its uncancelled state. 
244  **/
245 void 
246 g_cancellable_reset (GCancellable *cancellable)
247 {
248   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
249
250   G_LOCK(cancellable);
251   /* Make sure we're not leaving old cancel state around */
252   if (cancellable->cancelled)
253     {
254       char ch;
255       if (cancellable->cancel_pipe[0] != -1)
256         read (cancellable->cancel_pipe[0], &ch, 1);
257       cancellable->cancelled = FALSE;
258     }
259   G_UNLOCK(cancellable);
260 }
261
262 /**
263  * g_cancellable_is_cancelled:
264  * @cancellable: a #GCancellable or NULL.
265  * 
266  * Checks if a cancellable job has been cancelled.
267  * 
268  * Returns: %TRUE if @cancellable is cancelled, 
269  * FALSE if called with %NULL or if item is not cancelled. 
270  **/
271 gboolean
272 g_cancellable_is_cancelled (GCancellable *cancellable)
273 {
274   return cancellable != NULL && cancellable->cancelled;
275 }
276
277 /**
278  * g_cancellable_set_error_if_cancelled:
279  * @cancellable: a #GCancellable object.
280  * @error: #GError to append error state to.
281  * 
282  * If the @cancelalble is cancelled, sets the error to notify
283  * that the operation was cancelled.
284  * 
285  * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not.
286  **/
287 gboolean
288 g_cancellable_set_error_if_cancelled (GCancellable  *cancellable,
289                                       GError       **error)
290 {
291   if (g_cancellable_is_cancelled (cancellable))
292     {
293       g_set_error (error,
294                    G_IO_ERROR,
295                    G_IO_ERROR_CANCELLED,
296                    _("Operation was cancelled"));
297       return TRUE;
298     }
299   
300   return FALSE;
301 }
302
303 /**
304  * g_cancellable_get_fd:
305  * @cancellable: a #GCancellable.
306  * 
307  * Gets the file descriptor for a cancellable job. This can be used to
308  * implement cancellable operations on Unix systems. The returned fd will
309  * turn readable when @cancellable is cancelled.
310  * 
311  * Returns: A valid file descriptor. %-1 if the file descriptor 
312  * is not supported, or on errors. 
313  **/
314 int
315 g_cancellable_get_fd (GCancellable *cancellable)
316 {
317   int fd;
318   if (cancellable == NULL)
319     return -1;
320   
321   G_LOCK(cancellable);
322   if (!cancellable->allocated_pipe)
323     {
324       cancellable->allocated_pipe = TRUE;
325       g_cancellable_open_pipe (cancellable);
326     }
327   
328   fd = cancellable->cancel_pipe[0];
329   G_UNLOCK(cancellable);
330   
331   return fd;
332 }
333
334 /**
335  * g_cancellable_cancel:
336  * @cancellable: a #GCancellable object.
337  * 
338  * Will set @cancellable to cancelled, and will emit the CANCELLED
339  * signal.
340  *
341  * This function is thread-safe. In other words, you can safely call it from
342  * another thread than the one running an operation that was passed
343  * the @cancellable.
344  **/
345 void
346 g_cancellable_cancel (GCancellable *cancellable)
347 {
348   gboolean cancel;
349
350   cancel = FALSE;
351   
352   G_LOCK(cancellable);
353   if (cancellable != NULL &&
354       !cancellable->cancelled)
355     {
356       char ch = 'x';
357       cancel = TRUE;
358       cancellable->cancelled = TRUE;
359       if (cancellable->cancel_pipe[1] != -1)
360         write (cancellable->cancel_pipe[1], &ch, 1);
361     }
362   G_UNLOCK(cancellable);
363
364   if (cancel)
365     {
366       g_object_ref (cancellable);
367       g_signal_emit (cancellable, signals[CANCELLED], 0);
368       g_object_unref (cancellable);
369     }
370 }
371
372 #define __G_CANCELLABLE_C__
373 #include "gioaliasdef.c"