summaryrefslogtreecommitdiff
path: root/gobject/gclosure.h
blob: 4720fda0a360085b9293176efcc2011abe65d9d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/* GObject - GLib Type, Object, Parameter and Signal Library
 * Copyright (C) 2000 Red Hat, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __G_CLOSURE_H__
#define __G_CLOSURE_H__


#include        <gobject/gtype.h>


#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */



/* --- defines --- */
#define	G_CLOSURE_NEEDS_MARSHAL(closure) (((GClosure*) (closure))->marshal == NULL)
#define	G_CCLOSURE_SWAP_DATA(cclosure)	 (((GClosure*) (closure))->derivative_flag)


/* -- typedefs --- */
typedef struct _GClosure		 GClosure;
typedef struct _GClosureNotifyData	 GClosureNotifyData;
typedef	gpointer GCallback;
typedef void  (*GClosureNotify)		(gpointer	 data,
					 GClosure	*closure);
typedef void  (*GClosureMarshal)	(GClosure	*closure,
					 GValue         *return_value,
					 guint           n_param_values,
					 const GValue   *param_values,
					 gpointer        invocation_hint,
					 gpointer	 marshal_data);
typedef struct _GCClosure		 GCClosure;


/* --- structures --- */
struct _GClosureNotifyData
{
  gpointer       data;
  GClosureNotify notify;
};
struct _GClosure
{
  /*< private >*/	guint	 ref_count : 15;
  /*< private >*/	guint	 meta_marshal : 1;
  /*< private >*/	guint	 n_guards : 1;
  /*< private >*/	guint	 n_fnotifiers : 2;	/* finalization notifiers */
  /*< private >*/	guint	 n_inotifiers : 8;	/* invalidation notifiers */
  /*< private >*/	guint	 in_inotify : 1;
  /*< private >*/	guint	 floating : 1;
  /*< protected >*/	guint	 derivative_flag : 1;
  /*< puplic >*/	guint	 in_marshal : 1;
  /*< public >*/	guint	 is_invalid : 1;

  /*< private >*/	void   (*marshal)  (GClosure       *closure,
					    GValue /*out*/ *return_value,
					    guint           n_param_values,
					    const GValue   *param_values,
					    gpointer        invocation_hint,
					    gpointer	    marshal_data);
  /*< protected >*/	gpointer data;

  /*< private >*/	GClosureNotifyData *notifiers;

  /* invariants/constrains:
   * - ->marshal and ->data are _invalid_ as soon as ->is_invalid==TRUE
   * - invocation of all inotifiers occours prior to fnotifiers
   * - order of inotifiers is random
   *   inotifiers may _not_ free/invalidate parameter values (e.g. ->data)
   * - order of fnotifiers is random
   * - notifiers may only be removed before or during their invocation
   * - reference counting may only happen prior to fnotify invocation
   *   (in that sense, fnotifiers are really finalization handlers)
   */
};
/* closure for C function calls, callback() is the user function
 */
struct _GCClosure
{
  GClosure	closure;
  gpointer	callback;
};


/* --- prototypes --- */
GClosure*	g_cclosure_new			(GCallback	callback_func,
						 gpointer	user_data,
						 GClosureNotify destroy_data);
GClosure*	g_cclosure_new_swap		(GCallback	callback_func,
						 gpointer	user_data,
						 GClosureNotify destroy_data);
GClosure*	g_signal_type_closure_new	(GType          itype,
						 guint          struct_offset);


/* --- prototypes --- */
GClosure*	g_closure_ref			(GClosure	*closure);
void		g_closure_unref			(GClosure	*closure);
/* intimidating */
GClosure*	g_closure_new_simple		(guint		 sizeof_closure,
						 gpointer	 data);
void		g_closure_add_fnotify		(GClosure       *closure,
						 gpointer	 notify_data,
						 GClosureNotify	 notify_func);
void		g_closure_remove_fnotify	(GClosure       *closure,
						 gpointer	 notify_data,
						 GClosureNotify	 notify_func);
void		g_closure_add_inotify		(GClosure       *closure,
						 gpointer	 notify_data,
						 GClosureNotify	 notify_func);
void		g_closure_remove_inotify	(GClosure       *closure,
						 gpointer	 notify_data,
						 GClosureNotify	 notify_func);
void		g_closure_add_marshal_guards	(GClosure	*closure,
						 gpointer        pre_marshal_data,
						 GClosureNotify	 pre_marshal_notify,
						 gpointer        post_marshal_data,
						 GClosureNotify	 post_marshal_notify);
void		g_closure_set_marshal		(GClosure	*closure,
						 GClosureMarshal marshal);
void		g_closure_set_meta_marshal	(GClosure       *closure,
						 gpointer	 marshal_data,
						 GClosureMarshal meta_marshal);
void		g_closure_invalidate		(GClosure	*closure);
void		g_closure_invoke		(GClosure 	*closure,
						 GValue	/*out*/	*return_value,
						 guint		 n_param_values,
						 const GValue	*param_values,
						 gpointer	 invocation_hint);


/* FIXME:
  data_object::destroy		-> closure_invalidate();
  closure_invalidate()		-> disconnect(closure);
  disconnect(closure)		-> (unlink) closure_unref();
  closure_finalize()		-> g_free (data_string);
  
  1) need GObject and GType in glib
  2) need GParam
  3) need to resolve dtor cycles
  4) need GSignal move
  5) destroy on last caller ref or last data ref?
  
  
  random remarks:
  - don't mandate signals for GObject
  - OTOH, don't mandate GObject for GSignal
  - need marshaller repo with decent aliasing to base types
  - provide marshaller collection, virtually covering anything out there
  - at that point, still need GSignalCMarhsaller to g_signal_new() ?
  - can we combine varargs collect mechanisms with marshaller stubs?
  for out values (i.e. returntypes), that might get rid of the following
  point...
  - char* return signals with connections ala:
  connect({ return "static data that can't work"; }),
  connect({ return g_strdup ("properly duplicated string"); })
  won't work anymore. CRASH

  problems:
  - accumulator needs gboolean to indicate EMISSION_STOP
  - accumulator needs data
*/


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __G_CLOSURE_H__ */