(root)/
glib-2.79.0/
gobject/
gsourceclosure.c
       1  /* GObject - GLib Type, Object, Parameter and Signal Library
       2   * Copyright (C) 2001 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General
      17   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      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  #ifdef G_OS_UNIX
      29  #include "glib-unix.h"
      30  #endif
      31  
      32  G_DEFINE_BOXED_TYPE (GIOChannel, g_io_channel, g_io_channel_ref, g_io_channel_unref)
      33  
      34  GType
      35  g_io_condition_get_type (void)
      36  {
      37    static GType etype = 0;
      38  
      39    if (g_once_init_enter_pointer (&etype))
      40      {
      41        static const GFlagsValue values[] = {
      42  	{ G_IO_IN,   "G_IO_IN",   "in" },
      43  	{ G_IO_OUT,  "G_IO_OUT",  "out" },
      44  	{ G_IO_PRI,  "G_IO_PRI",  "pri" },
      45  	{ G_IO_ERR,  "G_IO_ERR",  "err" },
      46  	{ G_IO_HUP,  "G_IO_HUP",  "hup" },
      47  	{ G_IO_NVAL, "G_IO_NVAL", "nval" },
      48  	{ 0, NULL, NULL }
      49        };
      50        GType type_id = g_flags_register_static ("GIOCondition", values);
      51        g_once_init_leave_pointer (&etype, type_id);
      52      }
      53    return etype;
      54  }
      55  
      56  /* We need to hand-write this marshaler, since it doesn't have an
      57   * instance object.
      58   */
      59  static void
      60  source_closure_marshal_BOOLEAN__VOID (GClosure     *closure,
      61  				      GValue       *return_value,
      62  				      guint         n_param_values,
      63  				      const GValue *param_values,
      64  				      gpointer      invocation_hint,
      65  				      gpointer      marshal_data)
      66  {
      67    GSourceFunc callback;
      68    GCClosure *cc = (GCClosure*) closure;
      69    gboolean v_return;
      70  
      71    g_return_if_fail (return_value != NULL);
      72    g_return_if_fail (n_param_values == 0);
      73  
      74    callback = (GSourceFunc) (marshal_data ? marshal_data : cc->callback);
      75  
      76    v_return = callback (closure->data);
      77  
      78    g_value_set_boolean (return_value, v_return);
      79  }
      80  
      81  static gboolean
      82  io_watch_closure_callback (GIOChannel   *channel,
      83  			   GIOCondition  condition,
      84  			   gpointer      data)
      85  {
      86    GClosure *closure = data;
      87  
      88    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
      89    GValue result_value = G_VALUE_INIT;
      90    gboolean result;
      91  
      92    g_value_init (&result_value, G_TYPE_BOOLEAN);
      93    g_value_init (&params[0], G_TYPE_IO_CHANNEL);
      94    g_value_set_boxed (&params[0], channel);
      95  		     
      96    g_value_init (&params[1], G_TYPE_IO_CONDITION);
      97    g_value_set_flags (&params[1], condition);
      98  
      99    g_closure_invoke (closure, &result_value, 2, params, NULL);
     100  
     101    result = g_value_get_boolean (&result_value);
     102    g_value_unset (&result_value);
     103    g_value_unset (&params[0]);
     104    g_value_unset (&params[1]);
     105  
     106    return result;
     107  }
     108  
     109  static gboolean
     110  g_child_watch_closure_callback (GPid     pid,
     111                                  gint     status,
     112                                  gpointer data)
     113  {
     114    GClosure *closure = data;
     115  
     116    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
     117    GValue result_value = G_VALUE_INIT;
     118    gboolean result;
     119  
     120    g_value_init (&result_value, G_TYPE_BOOLEAN);
     121  
     122  #ifdef G_OS_UNIX
     123    g_value_init (&params[0], G_TYPE_ULONG);
     124    g_value_set_ulong (&params[0], pid);
     125  #endif
     126  #ifdef G_OS_WIN32
     127    g_value_init (&params[0], G_TYPE_POINTER);
     128    g_value_set_pointer (&params[0], pid);
     129  #endif
     130  
     131    g_value_init (&params[1], G_TYPE_INT);
     132    g_value_set_int (&params[1], status);
     133  
     134    g_closure_invoke (closure, &result_value, 2, params, NULL);
     135  
     136    result = g_value_get_boolean (&result_value);
     137    g_value_unset (&result_value);
     138    g_value_unset (&params[0]);
     139    g_value_unset (&params[1]);
     140  
     141    return result;
     142  }
     143  
     144  #ifdef G_OS_UNIX
     145  static gboolean
     146  g_unix_fd_source_closure_callback (int           fd,
     147                                     GIOCondition  condition,
     148                                     gpointer      data)
     149  {
     150    GClosure *closure = data;
     151  
     152    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
     153    GValue result_value = G_VALUE_INIT;
     154    gboolean result;
     155  
     156    g_value_init (&result_value, G_TYPE_BOOLEAN);
     157  
     158    g_value_init (&params[0], G_TYPE_INT);
     159    g_value_set_int (&params[0], fd);
     160  
     161    g_value_init (&params[1], G_TYPE_IO_CONDITION);
     162    g_value_set_flags (&params[1], condition);
     163  
     164    g_closure_invoke (closure, &result_value, 2, params, NULL);
     165  
     166    result = g_value_get_boolean (&result_value);
     167    g_value_unset (&result_value);
     168    g_value_unset (&params[0]);
     169    g_value_unset (&params[1]);
     170  
     171    return result;
     172  }
     173  #endif
     174  
     175  static gboolean
     176  source_closure_callback (gpointer data)
     177  {
     178    GClosure *closure = data;
     179    GValue result_value = G_VALUE_INIT;
     180    gboolean result;
     181  
     182    g_value_init (&result_value, G_TYPE_BOOLEAN);
     183    
     184    g_closure_invoke (closure, &result_value, 0, NULL, NULL);
     185  
     186    result = g_value_get_boolean (&result_value);
     187    g_value_unset (&result_value);
     188  
     189    return result;
     190  }
     191  
     192  static void
     193  closure_callback_get (gpointer     cb_data,
     194  		      GSource     *source,
     195  		      GSourceFunc *func,
     196  		      gpointer    *data)
     197  {
     198    GSourceFunc closure_callback = source->source_funcs->closure_callback;
     199  
     200    if (!closure_callback)
     201      {
     202        if (source->source_funcs == &g_io_watch_funcs)
     203          closure_callback = (GSourceFunc)io_watch_closure_callback;
     204        else if (source->source_funcs == &g_child_watch_funcs)
     205          closure_callback = (GSourceFunc)g_child_watch_closure_callback;
     206  #ifdef G_OS_UNIX
     207        else if (source->source_funcs == &g_unix_fd_source_funcs)
     208          closure_callback = (GSourceFunc)g_unix_fd_source_closure_callback;
     209  #endif
     210        else if (source->source_funcs == &g_timeout_funcs ||
     211  #ifdef G_OS_UNIX
     212                 source->source_funcs == &g_unix_signal_funcs ||
     213  #endif
     214                 source->source_funcs == &g_idle_funcs)
     215          closure_callback = source_closure_callback;
     216      }
     217  
     218    *func = closure_callback;
     219    *data = cb_data;
     220  }
     221  
     222  static GSourceCallbackFuncs closure_callback_funcs = {
     223    (void (*) (gpointer)) g_closure_ref,
     224    (void (*) (gpointer)) g_closure_unref,
     225    closure_callback_get
     226  };
     227  
     228  static void
     229  closure_invalidated (gpointer  user_data,
     230                       GClosure *closure)
     231  {
     232    g_source_destroy (user_data);
     233  }
     234  
     235  /**
     236   * g_source_set_closure:
     237   * @source: the source
     238   * @closure: a #GClosure
     239   *
     240   * Set the callback for a source as a #GClosure.
     241   *
     242   * If the source is not one of the standard GLib types, the @closure_callback
     243   * and @closure_marshal fields of the #GSourceFuncs structure must have been
     244   * filled in with pointers to appropriate functions.
     245   */
     246  void
     247  g_source_set_closure (GSource  *source,
     248  		      GClosure *closure)
     249  {
     250    g_return_if_fail (source != NULL);
     251    g_return_if_fail (closure != NULL);
     252  
     253    if (!source->source_funcs->closure_callback &&
     254  #ifdef G_OS_UNIX
     255        source->source_funcs != &g_unix_fd_source_funcs &&
     256        source->source_funcs != &g_unix_signal_funcs &&
     257  #endif
     258        source->source_funcs != &g_child_watch_funcs &&
     259        source->source_funcs != &g_io_watch_funcs &&
     260        source->source_funcs != &g_timeout_funcs &&
     261        source->source_funcs != &g_idle_funcs)
     262      {
     263        g_critical (G_STRLOC ": closure cannot be set on GSource without GSourceFuncs::closure_callback");
     264        return;
     265      }
     266  
     267    g_closure_ref (closure);
     268    g_closure_sink (closure);
     269    g_source_set_callback_indirect (source, closure, &closure_callback_funcs);
     270  
     271    g_closure_add_invalidate_notifier (closure, source, closure_invalidated);
     272  
     273    if (G_CLOSURE_NEEDS_MARSHAL (closure))
     274      {
     275        GClosureMarshal marshal = (GClosureMarshal)source->source_funcs->closure_marshal;
     276        if (marshal)
     277  	g_closure_set_marshal (closure, marshal);
     278        else if (source->source_funcs == &g_idle_funcs ||
     279  #ifdef G_OS_UNIX
     280                 source->source_funcs == &g_unix_signal_funcs ||
     281  #endif
     282                 source->source_funcs == &g_timeout_funcs)
     283  	g_closure_set_marshal (closure, source_closure_marshal_BOOLEAN__VOID);
     284        else
     285          g_closure_set_marshal (closure, g_cclosure_marshal_generic);
     286      }
     287  }
     288  
     289  static void
     290  dummy_closure_marshal (GClosure     *closure,
     291  		       GValue       *return_value,
     292  		       guint         n_param_values,
     293  		       const GValue *param_values,
     294  		       gpointer      invocation_hint,
     295  		       gpointer      marshal_data)
     296  {
     297    if (G_VALUE_HOLDS_BOOLEAN (return_value))
     298      g_value_set_boolean (return_value, TRUE);
     299  }
     300  
     301  /**
     302   * g_source_set_dummy_callback:
     303   * @source: the source
     304   *
     305   * Sets a dummy callback for @source. The callback will do nothing, and
     306   * if the source expects a #gboolean return value, it will return %TRUE.
     307   * (If the source expects any other type of return value, it will return
     308   * a 0/%NULL value; whatever g_value_init() initializes a #GValue to for
     309   * that type.)
     310   *
     311   * If the source is not one of the standard GLib types, the
     312   * @closure_callback and @closure_marshal fields of the #GSourceFuncs
     313   * structure must have been filled in with pointers to appropriate
     314   * functions.
     315   */
     316  void
     317  g_source_set_dummy_callback (GSource *source)
     318  {
     319    GClosure *closure;
     320  
     321    closure = g_closure_new_simple (sizeof (GClosure), NULL);
     322    g_closure_set_meta_marshal (closure, NULL, dummy_closure_marshal);
     323    g_source_set_closure (source, closure);
     324  }