source: trunk/third/glib2/gobject/gsourceclosure.c @ 20721

Revision 20721, 5.4 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20720, which included commits to RCS files with non-trunk default branches.
Line 
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 "gsourceclosure.h"
21#include "gboxed.h"
22#include "genums.h"
23#include "gmarshal.h"
24#include "gvalue.h"
25#include "gvaluetypes.h"
26
27/* This is needed for a proper GBoxedCopyFunc, until the g_io_channel_ref API
28 * returns it's GIOChannel itself #131076.
29 */
30static GIOChannel *
31wrap_g_io_channel_ref (GIOChannel *channel)
32{
33  g_io_channel_ref (channel);
34  return channel;
35}
36
37GType
38g_io_channel_get_type (void)
39{
40  static GType our_type = 0;
41 
42  if (our_type == 0)
43    our_type = g_boxed_type_register_static ("GIOChannel",
44                                             (GBoxedCopyFunc) wrap_g_io_channel_ref,
45                                             (GBoxedFreeFunc) g_io_channel_unref);
46
47  return our_type;
48}
49
50GType
51g_io_condition_get_type (void)
52{
53  static GType etype = 0;
54  if (etype == 0)
55    {
56      static const GFlagsValue values[] = {
57        { G_IO_IN,   "G_IO_IN",   "in" },
58        { G_IO_OUT,  "G_IO_OUT",  "out" },
59        { G_IO_PRI,  "G_IO_PRI",  "pri" },
60        { G_IO_ERR,  "G_IO_ERR",  "err" },
61        { G_IO_HUP,  "G_IO_HUP",  "hup" },
62        { G_IO_NVAL, "G_IO_NVAL", "nval" },
63        { 0, NULL, NULL }
64      };
65      etype = g_flags_register_static ("GIOCondition", values);
66    }
67  return etype;
68}
69
70/* We need to hand-write this marshaler, since it doesn't have an
71 * instance object.
72 */
73static void
74source_closure_marshal_BOOLEAN__VOID (GClosure     *closure,
75                                      GValue       *return_value,
76                                      guint         n_param_values,
77                                      const GValue *param_values,
78                                      gpointer      invocation_hint,
79                                      gpointer      marshal_data)
80{
81  GSourceFunc callback;
82  GCClosure *cc = (GCClosure*) closure;
83  gboolean v_return;
84
85  g_return_if_fail (return_value != NULL);
86  g_return_if_fail (n_param_values == 0);
87
88  callback = (GSourceFunc) (marshal_data ? marshal_data : cc->callback);
89
90  v_return = callback (closure->data);
91
92  g_value_set_boolean (return_value, v_return);
93}
94
95static gboolean
96io_watch_closure_callback (GIOChannel   *channel,
97                           GIOCondition  condition,
98                           gpointer      data)
99{
100  GClosure *closure = data;
101
102  GValue params[2] = { { 0, }, { 0, } };
103  GValue result_value = { 0, };
104  gboolean result;
105
106  g_value_init (&result_value, G_TYPE_BOOLEAN);
107  g_value_init (&params[0], G_TYPE_IO_CHANNEL);
108  g_value_set_boxed (&params[0], channel);
109                     
110  g_value_init (&params[1], G_TYPE_IO_CONDITION);
111  g_value_set_flags (&params[1], condition);
112
113  g_closure_invoke (closure, &result_value, 2, params, NULL);
114
115  result = g_value_get_boolean (&result_value);
116  g_value_unset (&result_value);
117  g_value_unset (&params[0]);
118  g_value_unset (&params[1]);
119
120  return result;
121}
122
123static gboolean
124source_closure_callback (gpointer data)
125{
126  GClosure *closure = data;
127  GValue result_value = { 0, };
128  gboolean result;
129
130  g_value_init (&result_value, G_TYPE_BOOLEAN);
131 
132  g_closure_invoke (closure, &result_value, 0, NULL, NULL);
133
134  result = g_value_get_boolean (&result_value);
135  g_value_unset (&result_value);
136
137  return result;
138}
139
140static void
141closure_callback_get (gpointer     cb_data,
142                      GSource     *source,
143                      GSourceFunc *func,
144                      gpointer    *data)
145{
146  GSourceFunc closure_callback = source->source_funcs->closure_callback;
147
148  if (!closure_callback)
149    {
150      if (source->source_funcs == &g_io_watch_funcs)
151        closure_callback = (GSourceFunc)io_watch_closure_callback;
152      else if (source->source_funcs == &g_timeout_funcs ||
153               source->source_funcs == &g_idle_funcs)
154        closure_callback = source_closure_callback;
155    }
156
157  *func = closure_callback;
158  *data = cb_data;
159}
160
161static GSourceCallbackFuncs closure_callback_funcs = {
162  (void (*) (gpointer)) g_closure_ref,
163  (void (*) (gpointer)) g_closure_unref,
164  closure_callback_get
165};
166
167void
168g_source_set_closure (GSource  *source,
169                      GClosure *closure)
170{
171  g_return_if_fail (source != NULL);
172  g_return_if_fail (closure != NULL);
173
174  if (!source->source_funcs->closure_callback &&
175      source->source_funcs != &g_io_watch_funcs &&
176      source->source_funcs != &g_timeout_funcs &&
177      source->source_funcs != &g_idle_funcs)
178    {
179      g_critical (G_STRLOC "closure can not be set on closure without GSourceFuncs::closure_callback\n");
180      return;
181    }
182
183  g_closure_ref (closure);
184  g_closure_sink (closure);
185  g_source_set_callback_indirect (source, closure, &closure_callback_funcs);
186
187  if (G_CLOSURE_NEEDS_MARSHAL (closure))
188    {
189      GClosureMarshal marshal = (GClosureMarshal)source->source_funcs->closure_marshal;
190      if (!marshal)
191        {
192          if (source->source_funcs == &g_idle_funcs ||
193              source->source_funcs == &g_timeout_funcs)
194            marshal = source_closure_marshal_BOOLEAN__VOID;
195          else if (source->source_funcs == &g_io_watch_funcs)
196            marshal = g_cclosure_marshal_BOOLEAN__FLAGS;
197        }
198      if (marshal)
199        g_closure_set_marshal (closure, marshal);
200    }
201}
Note: See TracBrowser for help on using the repository browser.