Home | History | Annotate | Download | only in gio
      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