Home | History | Annotate | Download | only in gobject
      1 /* GObject - GLib Type, Object, Parameter and Signal Library
      2  * Copyright (C) 2001 Red Hat, Inc.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Lesser General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General
     15  * Public License along with this library; if not, write to the
     16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     17  * Boston, MA 02111-1307, USA.
     18  */
     19 
     20 #include "config.h"
     21 
     22 #include "gsourceclosure.h"
     23 #include "gboxed.h"
     24 #include "genums.h"
     25 #include "gmarshal.h"
     26 #include "gvalue.h"
     27 #include "gvaluetypes.h"
     28 #include "gobjectalias.h"
     29 
     30 
     31 GType
     32 g_io_channel_get_type (void)
     33 {
     34   static GType our_type = 0;
     35 
     36   if (our_type == 0)
     37     our_type = g_boxed_type_register_static ("GIOChannel",
     38 					     (GBoxedCopyFunc) g_io_channel_ref,
     39 					     (GBoxedFreeFunc) g_io_channel_unref);
     40 
     41   return our_type;
     42 }
     43 
     44 GType
     45 g_io_condition_get_type (void)
     46 {
     47   static GType etype = 0;
     48   if (etype == 0)
     49     {
     50       static const GFlagsValue values[] = {
     51 	{ G_IO_IN,   "G_IO_IN",   "in" },
     52 	{ G_IO_OUT,  "G_IO_OUT",  "out" },
     53 	{ G_IO_PRI,  "G_IO_PRI",  "pri" },
     54 	{ G_IO_ERR,  "G_IO_ERR",  "err" },
     55 	{ G_IO_HUP,  "G_IO_HUP",  "hup" },
     56 	{ G_IO_NVAL, "G_IO_NVAL", "nval" },
     57 	{ 0, NULL, NULL }
     58       };
     59       etype = g_flags_register_static ("GIOCondition", values);
     60     }
     61   return etype;
     62 }
     63 
     64 /* We need to hand-write this marshaler, since it doesn't have an
     65  * instance object.
     66  */
     67 static void
     68 source_closure_marshal_BOOLEAN__VOID (GClosure     *closure,
     69 				      GValue       *return_value,
     70 				      guint         n_param_values,
     71 				      const GValue *param_values,
     72 				      gpointer      invocation_hint,
     73 				      gpointer      marshal_data)
     74 {
     75   GSourceFunc callback;
     76   GCClosure *cc = (GCClosure*) closure;
     77   gboolean v_return;
     78 
     79   g_return_if_fail (return_value != NULL);
     80   g_return_if_fail (n_param_values == 0);
     81 
     82   callback = (GSourceFunc) (marshal_data ? marshal_data : cc->callback);
     83 
     84   v_return = callback (closure->data);
     85 
     86   g_value_set_boolean (return_value, v_return);
     87 }
     88 
     89 static gboolean
     90 io_watch_closure_callback (GIOChannel   *channel,
     91 			   GIOCondition  condition,
     92 			   gpointer      data)
     93 {
     94   GClosure *closure = data;
     95 
     96   GValue params[2] = { { 0, }, { 0, } };
     97   GValue result_value = { 0, };
     98   gboolean result;
     99 
    100   g_value_init (&result_value, G_TYPE_BOOLEAN);
    101   g_value_init (&params[0], G_TYPE_IO_CHANNEL);
    102   g_value_set_boxed (&params[0], channel);
    103 
    104   g_value_init (&params[1], G_TYPE_IO_CONDITION);
    105   g_value_set_flags (&params[1], condition);
    106 
    107   g_closure_invoke (closure, &result_value, 2, params, NULL);
    108 
    109   result = g_value_get_boolean (&result_value);
    110   g_value_unset (&result_value);
    111   g_value_unset (&params[0]);
    112   g_value_unset (&params[1]);
    113 
    114   return result;
    115 }
    116 
    117 static gboolean
    118 source_closure_callback (gpointer data)
    119 {
    120   GClosure *closure = data;
    121   GValue result_value = { 0, };
    122   gboolean result;
    123 
    124   g_value_init (&result_value, G_TYPE_BOOLEAN);
    125 
    126   g_closure_invoke (closure, &result_value, 0, NULL, NULL);
    127 
    128   result = g_value_get_boolean (&result_value);
    129   g_value_unset (&result_value);
    130 
    131   return result;
    132 }
    133 
    134 static void
    135 closure_callback_get (gpointer     cb_data,
    136 		      GSource     *source,
    137 		      GSourceFunc *func,
    138 		      gpointer    *data)
    139 {
    140   GSourceFunc closure_callback = source->source_funcs->closure_callback;
    141 
    142   if (!closure_callback)
    143     {
    144       if (source->source_funcs == &g_io_watch_funcs)
    145 	closure_callback = (GSourceFunc)io_watch_closure_callback;
    146       else if (source->source_funcs == &g_timeout_funcs ||
    147 	       source->source_funcs == &g_idle_funcs)
    148 	closure_callback = source_closure_callback;
    149     }
    150 
    151   *func = closure_callback;
    152   *data = cb_data;
    153 }
    154 
    155 static GSourceCallbackFuncs closure_callback_funcs = {
    156   (void (*) (gpointer)) g_closure_ref,
    157   (void (*) (gpointer)) g_closure_unref,
    158   closure_callback_get
    159 };
    160 
    161 /**
    162  * g_source_set_closure:
    163  * @source: the source
    164  * @closure: a #GClosure
    165  *
    166  * Set the callback for a source as a #GClosure.
    167  *
    168  * If the source is not one of the standard GLib types, the @closure_callback
    169  * and @closure_marshal fields of the #GSourceFuncs structure must have been
    170  * filled in with pointers to appropriate functions.
    171  */
    172 void
    173 g_source_set_closure (GSource  *source,
    174 		      GClosure *closure)
    175 {
    176   g_return_if_fail (source != NULL);
    177   g_return_if_fail (closure != NULL);
    178 
    179   if (!source->source_funcs->closure_callback &&
    180       source->source_funcs != &g_io_watch_funcs &&
    181       source->source_funcs != &g_timeout_funcs &&
    182       source->source_funcs != &g_idle_funcs)
    183     {
    184       g_critical (G_STRLOC "closure can not be set on closure without GSourceFuncs::closure_callback\n");
    185       return;
    186     }
    187 
    188   g_closure_ref (closure);
    189   g_closure_sink (closure);
    190   g_source_set_callback_indirect (source, closure, &closure_callback_funcs);
    191 
    192   if (G_CLOSURE_NEEDS_MARSHAL (closure))
    193     {
    194       GClosureMarshal marshal = (GClosureMarshal)source->source_funcs->closure_marshal;
    195       if (!marshal)
    196 	{
    197 	  if (source->source_funcs == &g_idle_funcs ||
    198 	      source->source_funcs == &g_timeout_funcs)
    199 	    marshal = source_closure_marshal_BOOLEAN__VOID;
    200 	  else if (source->source_funcs == &g_io_watch_funcs)
    201 	    marshal = g_cclosure_marshal_BOOLEAN__FLAGS;
    202 	}
    203       if (marshal)
    204 	g_closure_set_marshal (closure, marshal);
    205     }
    206 }
    207 
    208 #define __G_SOURCECLOSURE_C__
    209 #include "gobjectaliasdef.c"
    210