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 (at) redhat.com> 21 */ 22 23 #include "config.h" 24 25 #include "gasynchelper.h" 26 27 #include "gioalias.h" 28 29 /** 30 * SECTION:gasynchelper 31 * @short_description: Asynchronous Helper Functions 32 * @include: gio/gio.h 33 * @see_also: #GAsyncReady 34 * 35 * Provides helper functions for asynchronous operations. 36 * 37 **/ 38 39 static void 40 async_result_free (gpointer data) 41 { 42 GAsyncResultData *res = data; 43 44 if (res->error) 45 g_error_free (res->error); 46 47 g_object_unref (res->async_object); 48 49 g_free (res); 50 } 51 52 void 53 _g_queue_async_result (GAsyncResultData *result, 54 gpointer async_object, 55 GError *error, 56 gpointer user_data, 57 GSourceFunc source_func) 58 { 59 GSource *source; 60 61 g_return_if_fail (G_IS_OBJECT (async_object)); 62 63 result->async_object = g_object_ref (async_object); 64 result->user_data = user_data; 65 result->error = error; 66 67 source = g_idle_source_new (); 68 g_source_set_priority (source, G_PRIORITY_DEFAULT); 69 g_source_set_callback (source, source_func, result, async_result_free); 70 g_source_attach (source, NULL); 71 g_source_unref (source); 72 } 73 74 /************************************************************************* 75 * fd source * 76 ************************************************************************/ 77 78 typedef struct 79 { 80 GSource source; 81 GPollFD pollfd; 82 GCancellable *cancellable; 83 gulong cancelled_tag; 84 } FDSource; 85 86 static gboolean 87 fd_source_prepare (GSource *source, 88 gint *timeout) 89 { 90 FDSource *fd_source = (FDSource *)source; 91 *timeout = -1; 92 93 return g_cancellable_is_cancelled (fd_source->cancellable); 94 } 95 96 static gboolean 97 fd_source_check (GSource *source) 98 { 99 FDSource *fd_source = (FDSource *)source; 100 101 return 102 g_cancellable_is_cancelled (fd_source->cancellable) || 103 fd_source->pollfd.revents != 0; 104 } 105 106 static gboolean 107 fd_source_dispatch (GSource *source, 108 GSourceFunc callback, 109 gpointer user_data) 110 111 { 112 GFDSourceFunc func = (GFDSourceFunc)callback; 113 FDSource *fd_source = (FDSource *)source; 114 115 g_warn_if_fail (func != NULL); 116 117 return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd); 118 } 119 120 static void 121 fd_source_finalize (GSource *source) 122 { 123 FDSource *fd_source = (FDSource *)source; 124 125 if (fd_source->cancelled_tag) 126 g_signal_handler_disconnect (fd_source->cancellable, 127 fd_source->cancelled_tag); 128 129 if (fd_source->cancellable) 130 g_object_unref (fd_source->cancellable); 131 } 132 133 static GSourceFuncs fd_source_funcs = { 134 fd_source_prepare, 135 fd_source_check, 136 fd_source_dispatch, 137 fd_source_finalize 138 }; 139 140 /* Might be called on another thread */ 141 static void 142 fd_source_cancelled_cb (GCancellable *cancellable, 143 gpointer data) 144 { 145 /* Wake up the mainloop in case we're waiting on async calls with FDSource */ 146 g_main_context_wakeup (NULL); 147 } 148 149 GSource * 150 _g_fd_source_new (int fd, 151 gushort events, 152 GCancellable *cancellable) 153 { 154 GSource *source; 155 FDSource *fd_source; 156 157 source = g_source_new (&fd_source_funcs, sizeof (FDSource)); 158 fd_source = (FDSource *)source; 159 160 if (cancellable) 161 fd_source->cancellable = g_object_ref (cancellable); 162 163 fd_source->pollfd.fd = fd; 164 fd_source->pollfd.events = events; 165 g_source_add_poll (source, &fd_source->pollfd); 166 167 if (cancellable) 168 fd_source->cancelled_tag = 169 g_signal_connect_data (cancellable, "cancelled", 170 (GCallback)fd_source_cancelled_cb, 171 NULL, NULL, 172 0); 173 174 return source; 175 } 176