glib2 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +3023 -0
- data/README +28 -0
- data/Rakefile +87 -0
- data/extconf.rb +61 -0
- data/sample/bookmarkfile.rb +66 -0
- data/sample/completion.rb +45 -0
- data/sample/idle.rb +41 -0
- data/sample/iochannel.rb +44 -0
- data/sample/keyfile.rb +62 -0
- data/sample/shell.rb +36 -0
- data/sample/spawn.rb +25 -0
- data/sample/timeout.rb +28 -0
- data/sample/timeout2.rb +35 -0
- data/sample/timer.rb +40 -0
- data/sample/type-register.rb +103 -0
- data/sample/type-register2.rb +104 -0
- data/sample/utils.rb +54 -0
- data/src/glib-enum-types.c +1032 -0
- data/src/glib-enum-types.h +140 -0
- data/src/lib/glib-mkenums.rb +199 -0
- data/src/lib/glib2.rb +220 -0
- data/src/lib/mkmf-gnome2.rb +390 -0
- data/src/lib/pkg-config.rb +137 -0
- data/src/rbgcompat.h +30 -0
- data/src/rbglib.c +320 -0
- data/src/rbglib.h +96 -0
- data/src/rbglib_bookmarkfile.c +595 -0
- data/src/rbglib_completion.c +192 -0
- data/src/rbglib_convert.c +195 -0
- data/src/rbglib_error.c +95 -0
- data/src/rbglib_fileutils.c +83 -0
- data/src/rbglib_i18n.c +44 -0
- data/src/rbglib_int64.c +157 -0
- data/src/rbglib_iochannel.c +883 -0
- data/src/rbglib_keyfile.c +846 -0
- data/src/rbglib_maincontext.c +917 -0
- data/src/rbglib_mainloop.c +87 -0
- data/src/rbglib_messages.c +150 -0
- data/src/rbglib_pollfd.c +111 -0
- data/src/rbglib_shell.c +68 -0
- data/src/rbglib_source.c +190 -0
- data/src/rbglib_spawn.c +345 -0
- data/src/rbglib_threads.c +51 -0
- data/src/rbglib_timer.c +127 -0
- data/src/rbglib_unicode.c +611 -0
- data/src/rbglib_utils.c +386 -0
- data/src/rbglib_win32.c +136 -0
- data/src/rbgobj_boxed.c +251 -0
- data/src/rbgobj_closure.c +337 -0
- data/src/rbgobj_convert.c +167 -0
- data/src/rbgobj_enums.c +961 -0
- data/src/rbgobj_fundamental.c +30 -0
- data/src/rbgobj_object.c +892 -0
- data/src/rbgobj_param.c +390 -0
- data/src/rbgobj_paramspecs.c +305 -0
- data/src/rbgobj_signal.c +963 -0
- data/src/rbgobj_strv.c +61 -0
- data/src/rbgobj_type.c +851 -0
- data/src/rbgobj_typeinstance.c +121 -0
- data/src/rbgobj_typeinterface.c +148 -0
- data/src/rbgobj_typemodule.c +66 -0
- data/src/rbgobj_typeplugin.c +49 -0
- data/src/rbgobj_value.c +313 -0
- data/src/rbgobj_valuearray.c +59 -0
- data/src/rbgobj_valuetypes.c +298 -0
- data/src/rbgobject.c +406 -0
- data/src/rbgobject.h +265 -0
- data/src/rbgprivate.h +88 -0
- data/src/rbgutil.c +222 -0
- data/src/rbgutil.h +82 -0
- data/src/rbgutil_callback.c +231 -0
- data/test/glib-test-init.rb +6 -0
- data/test/glib-test-utils.rb +12 -0
- data/test/run-test.rb +25 -0
- data/test/test_enum.rb +99 -0
- data/test/test_file_utils.rb +15 -0
- data/test/test_glib2.rb +120 -0
- data/test/test_iochannel.rb +275 -0
- data/test/test_key_file.rb +38 -0
- data/test/test_mkenums.rb +25 -0
- data/test/test_signal.rb +20 -0
- data/test/test_timeout.rb +28 -0
- data/test/test_unicode.rb +369 -0
- data/test/test_utils.rb +37 -0
- data/test/test_win32.rb +13 -0
- metadata +165 -0
@@ -0,0 +1,917 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/************************************************
|
3
|
+
|
4
|
+
rbglib_maincontext.c -
|
5
|
+
|
6
|
+
$Author: ktou $
|
7
|
+
$Date: 2007/08/30 10:13:44 $
|
8
|
+
|
9
|
+
Copyright (C) 2005 Masao Mutoh
|
10
|
+
************************************************/
|
11
|
+
|
12
|
+
#include "rbgprivate.h"
|
13
|
+
|
14
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
15
|
+
# include <version.h>
|
16
|
+
# include <rubysig.h>
|
17
|
+
# include <node.h>
|
18
|
+
# include <time.h>
|
19
|
+
# ifdef HAVE_CURR_THREAD
|
20
|
+
# define rb_curr_thread curr_thread
|
21
|
+
# endif
|
22
|
+
#endif
|
23
|
+
|
24
|
+
/*
|
25
|
+
static ID id_poll_func;
|
26
|
+
*/
|
27
|
+
static ID id_call;
|
28
|
+
|
29
|
+
|
30
|
+
static VALUE mGLibSource;
|
31
|
+
static ID id__callbacks__;
|
32
|
+
static GHashTable *callbacks_table;
|
33
|
+
|
34
|
+
typedef struct _callback_info_t
|
35
|
+
{
|
36
|
+
VALUE callback;
|
37
|
+
guint id;
|
38
|
+
} callback_info_t;
|
39
|
+
|
40
|
+
/*****************************************/
|
41
|
+
static GPollFunc default_poll_func;
|
42
|
+
|
43
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
44
|
+
|
45
|
+
/* just for ruby-1.9.0. */
|
46
|
+
#if !defined(RUBY_UBF_IO) && defined(RB_UBF_DFL)
|
47
|
+
# define RUBY_UBF_IO RB_UBF_DFL
|
48
|
+
#endif
|
49
|
+
|
50
|
+
typedef struct _PollInfo
|
51
|
+
{
|
52
|
+
GPollFD *ufds;
|
53
|
+
guint nfsd;
|
54
|
+
gint timeout;
|
55
|
+
gint result;
|
56
|
+
} PollInfo;
|
57
|
+
|
58
|
+
static VALUE
|
59
|
+
rg_poll_in_blocking(void *data)
|
60
|
+
{
|
61
|
+
PollInfo *info = data;
|
62
|
+
|
63
|
+
info->result = default_poll_func(info->ufds, info->nfsd, info->timeout);
|
64
|
+
|
65
|
+
return Qnil;
|
66
|
+
}
|
67
|
+
|
68
|
+
static gint
|
69
|
+
rg_poll(GPollFD *ufds, guint nfsd, gint timeout)
|
70
|
+
{
|
71
|
+
PollInfo info;
|
72
|
+
|
73
|
+
info.ufds = ufds;
|
74
|
+
info.nfsd = nfsd;
|
75
|
+
info.timeout = timeout;
|
76
|
+
info.result = 0;
|
77
|
+
|
78
|
+
rb_thread_blocking_region(rg_poll_in_blocking, &info, RUBY_UBF_IO, NULL);
|
79
|
+
|
80
|
+
return info.result;
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
ruby_source_set_priority (VALUE self, VALUE priority)
|
85
|
+
{
|
86
|
+
return Qnil;
|
87
|
+
}
|
88
|
+
|
89
|
+
#else
|
90
|
+
static gint
|
91
|
+
rg_poll(GPollFD *ufds, guint nfsd, gint timeout)
|
92
|
+
{
|
93
|
+
gint result;
|
94
|
+
|
95
|
+
TRAP_BEG;
|
96
|
+
result = default_poll_func(ufds, nfsd, timeout);
|
97
|
+
TRAP_END;
|
98
|
+
|
99
|
+
return result;
|
100
|
+
}
|
101
|
+
#endif
|
102
|
+
|
103
|
+
static void
|
104
|
+
restore_poll_func(VALUE data)
|
105
|
+
{
|
106
|
+
if (g_main_context_get_poll_func(NULL) == (GPollFunc)rg_poll) {
|
107
|
+
g_main_context_set_poll_func(NULL, default_poll_func);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
112
|
+
static guint ruby_source_id = 0;
|
113
|
+
|
114
|
+
/* from eval.c */
|
115
|
+
#define WAIT_FD (1<<0)
|
116
|
+
#define WAIT_SELECT (1<<1)
|
117
|
+
#define WAIT_TIME (1<<2)
|
118
|
+
#define WAIT_JOIN (1<<3)
|
119
|
+
#define WAIT_PID (1<<4)
|
120
|
+
|
121
|
+
#define DELAY_INFTY 1E30
|
122
|
+
|
123
|
+
#ifdef RUBY_RELEASE_YEAR
|
124
|
+
# define CHECK_RUBY_RELEASE_DATE(year, month, day) \
|
125
|
+
(RUBY_RELEASE_YEAR >= (year) && \
|
126
|
+
RUBY_RELEASE_MONTH >= (month) && \
|
127
|
+
RUBY_RELEASE_DAY >= (day))
|
128
|
+
#else
|
129
|
+
# define CHECK_RUBY_RELEASE_DATE(year, month, day) 0
|
130
|
+
#endif
|
131
|
+
|
132
|
+
static double
|
133
|
+
timeofday()
|
134
|
+
{
|
135
|
+
struct timeval tv;
|
136
|
+
#if CHECK_RUBY_RELEASE_DATE(2009, 1, 7)
|
137
|
+
/* The following CLOCK_MONOTONIC change was introduced into
|
138
|
+
* Ruby 1.8.6 and 1.8.7 at 2009-01-07.
|
139
|
+
*
|
140
|
+
* 1.8.6:
|
141
|
+
* Wed Jan 7 10:06:12 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
142
|
+
*
|
143
|
+
* * eval.c (timeofday): use monotonic clock. based on a patch
|
144
|
+
* from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
|
145
|
+
*
|
146
|
+
* 1.8.7:
|
147
|
+
* Wed Jan 7 10:09:46 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
148
|
+
*
|
149
|
+
* * eval.c (timeofday): use monotonic clock. based on a patch
|
150
|
+
* from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
|
151
|
+
*/
|
152
|
+
# ifdef CLOCK_MONOTONIC
|
153
|
+
struct timespec tp;
|
154
|
+
|
155
|
+
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
|
156
|
+
return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
|
157
|
+
}
|
158
|
+
# endif
|
159
|
+
#endif
|
160
|
+
gettimeofday(&tv, NULL);
|
161
|
+
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
|
162
|
+
}
|
163
|
+
|
164
|
+
/*****************************************/
|
165
|
+
typedef struct _RGSource
|
166
|
+
{
|
167
|
+
GSource source;
|
168
|
+
|
169
|
+
GList *poll_fds;
|
170
|
+
GList *old_poll_fds;
|
171
|
+
gboolean ready;
|
172
|
+
} RGSource;
|
173
|
+
|
174
|
+
static void
|
175
|
+
source_cleanup_poll_fds(GSource *source)
|
176
|
+
{
|
177
|
+
RGSource *rg_source = (RGSource *)source;
|
178
|
+
GList *node;
|
179
|
+
|
180
|
+
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
|
181
|
+
GPollFD *poll_fd = node->data;
|
182
|
+
|
183
|
+
g_source_remove_poll(source, poll_fd);
|
184
|
+
g_slice_free(GPollFD, poll_fd);
|
185
|
+
}
|
186
|
+
g_list_free(rg_source->old_poll_fds);
|
187
|
+
rg_source->old_poll_fds = NULL;
|
188
|
+
}
|
189
|
+
|
190
|
+
static inline void
|
191
|
+
source_prepare_add_poll_fd(GSource *source, gint fd, guchar events)
|
192
|
+
{
|
193
|
+
GPollFD *poll_fd;
|
194
|
+
GList *node;
|
195
|
+
RGSource *rg_source = (RGSource *)source;
|
196
|
+
|
197
|
+
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
|
198
|
+
poll_fd = node->data;
|
199
|
+
if (poll_fd->fd == fd && poll_fd->events == events) {
|
200
|
+
rg_source->old_poll_fds =
|
201
|
+
g_list_remove_link(rg_source->old_poll_fds, node);
|
202
|
+
rg_source->poll_fds = g_list_concat(rg_source->poll_fds, node);
|
203
|
+
return;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
poll_fd = g_slice_new0(GPollFD);
|
208
|
+
poll_fd->fd = fd;
|
209
|
+
poll_fd->events = events;
|
210
|
+
|
211
|
+
g_source_add_poll(source, poll_fd);
|
212
|
+
rg_source->poll_fds = g_list_prepend(rg_source->poll_fds, poll_fd);
|
213
|
+
}
|
214
|
+
|
215
|
+
static inline void
|
216
|
+
source_prepare_add_poll(GSource *source, rb_thread_t thread)
|
217
|
+
{
|
218
|
+
if (thread->wait_for == WAIT_FD) {
|
219
|
+
/* The thread is blocked on thread->fd for read. */
|
220
|
+
source_prepare_add_poll_fd(source, thread->fd, G_IO_IN);
|
221
|
+
return;
|
222
|
+
}
|
223
|
+
|
224
|
+
if (thread->wait_for & WAIT_SELECT) {
|
225
|
+
/* thread->fd is the maximum fd of the fds in the various sets. Need to
|
226
|
+
* check the sets to see which fd's to wait for */
|
227
|
+
int fd;
|
228
|
+
|
229
|
+
for (fd = 0; fd < thread->fd; fd++) {
|
230
|
+
gushort events = 0;
|
231
|
+
|
232
|
+
if (FD_ISSET(fd, &thread->readfds))
|
233
|
+
events |= G_IO_IN;
|
234
|
+
if (FD_ISSET(fd, &thread->writefds))
|
235
|
+
events |= G_IO_OUT;
|
236
|
+
if (FD_ISSET(fd, &thread->exceptfds))
|
237
|
+
events |= G_IO_PRI | G_IO_ERR | G_IO_HUP;
|
238
|
+
|
239
|
+
if (events != 0)
|
240
|
+
source_prepare_add_poll_fd(source, fd, events);
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
static inline gboolean
|
246
|
+
source_prepare_setup_poll_fd(GSource *source, gint *timeout)
|
247
|
+
{
|
248
|
+
RGSource *rg_source = (RGSource *)source;
|
249
|
+
rb_thread_t thread;
|
250
|
+
gdouble now;
|
251
|
+
|
252
|
+
g_assert(rg_source->old_poll_fds == NULL);
|
253
|
+
rg_source->old_poll_fds = rg_source->poll_fds;
|
254
|
+
rg_source->poll_fds = NULL;
|
255
|
+
|
256
|
+
now = timeofday();
|
257
|
+
thread = rb_curr_thread;
|
258
|
+
do {
|
259
|
+
thread = thread->next;
|
260
|
+
|
261
|
+
if ((thread->wait_for == 0 && thread->status == THREAD_RUNNABLE &&
|
262
|
+
thread != rb_curr_thread) ||
|
263
|
+
(thread->wait_for & WAIT_JOIN &&
|
264
|
+
thread->join->status == THREAD_KILLED)) {
|
265
|
+
rg_source->poll_fds = g_list_concat(rg_source->poll_fds,
|
266
|
+
rg_source->old_poll_fds);
|
267
|
+
rg_source->old_poll_fds = NULL;
|
268
|
+
return TRUE;
|
269
|
+
}
|
270
|
+
|
271
|
+
if (thread->wait_for & WAIT_TIME && thread->delay != DELAY_INFTY) {
|
272
|
+
gint delay;
|
273
|
+
|
274
|
+
delay = (thread->delay - now) * 1000;
|
275
|
+
if (delay <= 0) {
|
276
|
+
rg_source->poll_fds = g_list_concat(rg_source->poll_fds,
|
277
|
+
rg_source->old_poll_fds);
|
278
|
+
rg_source->old_poll_fds = NULL;
|
279
|
+
return TRUE;
|
280
|
+
}
|
281
|
+
if (*timeout == -1 || delay < *timeout)
|
282
|
+
*timeout = delay;
|
283
|
+
}
|
284
|
+
|
285
|
+
if (thread->wait_for == WAIT_FD || thread->wait_for & WAIT_SELECT)
|
286
|
+
source_prepare_add_poll(source, thread);
|
287
|
+
} while (thread != rb_curr_thread);
|
288
|
+
|
289
|
+
source_cleanup_poll_fds(source);
|
290
|
+
|
291
|
+
return FALSE;
|
292
|
+
}
|
293
|
+
|
294
|
+
static gboolean
|
295
|
+
source_prepare(GSource *source, gint *timeout)
|
296
|
+
{
|
297
|
+
RGSource *rg_source = (RGSource *)source;
|
298
|
+
|
299
|
+
*timeout = -1;
|
300
|
+
rg_source->ready = source_prepare_setup_poll_fd(source, timeout);
|
301
|
+
|
302
|
+
return rg_source->ready;
|
303
|
+
}
|
304
|
+
|
305
|
+
static gboolean
|
306
|
+
source_check(GSource *source)
|
307
|
+
{
|
308
|
+
RGSource *rg_source = (RGSource *)source;
|
309
|
+
GList *node;
|
310
|
+
|
311
|
+
if (rg_source->ready)
|
312
|
+
return TRUE;
|
313
|
+
|
314
|
+
for (node = rg_source->poll_fds; node; node = g_list_next(node)) {
|
315
|
+
GPollFD *poll_fd = node->data;
|
316
|
+
|
317
|
+
if (poll_fd->revents)
|
318
|
+
return TRUE;
|
319
|
+
}
|
320
|
+
|
321
|
+
return FALSE;
|
322
|
+
}
|
323
|
+
|
324
|
+
static gboolean
|
325
|
+
source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
|
326
|
+
{
|
327
|
+
TRAP_BEG;
|
328
|
+
rb_thread_schedule();
|
329
|
+
TRAP_END;
|
330
|
+
|
331
|
+
return TRUE;
|
332
|
+
}
|
333
|
+
|
334
|
+
static void
|
335
|
+
source_finalize(GSource *source)
|
336
|
+
{
|
337
|
+
RGSource *rg_source = (RGSource *)source;
|
338
|
+
GList *node;
|
339
|
+
|
340
|
+
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
|
341
|
+
GPollFD *poll_fd = node->data;
|
342
|
+
g_slice_free(GPollFD, poll_fd);
|
343
|
+
}
|
344
|
+
|
345
|
+
for (node = rg_source->poll_fds; node; node = g_list_next(node)) {
|
346
|
+
GPollFD *poll_fd = node->data;
|
347
|
+
g_slice_free(GPollFD, poll_fd);
|
348
|
+
}
|
349
|
+
|
350
|
+
g_list_free(rg_source->old_poll_fds);
|
351
|
+
rg_source->old_poll_fds = NULL;
|
352
|
+
|
353
|
+
g_list_free(rg_source->poll_fds);
|
354
|
+
rg_source->poll_fds = NULL;
|
355
|
+
}
|
356
|
+
|
357
|
+
static GSourceFuncs source_funcs = {
|
358
|
+
source_prepare,
|
359
|
+
source_check,
|
360
|
+
source_dispatch,
|
361
|
+
source_finalize
|
362
|
+
};
|
363
|
+
|
364
|
+
static GSource *
|
365
|
+
ruby_source_new(void)
|
366
|
+
{
|
367
|
+
GSource *source;
|
368
|
+
RGSource *rg_source;
|
369
|
+
|
370
|
+
source = g_source_new(&source_funcs, sizeof(RGSource));
|
371
|
+
g_source_set_can_recurse(source, TRUE);
|
372
|
+
|
373
|
+
rg_source = (RGSource *)source;
|
374
|
+
rg_source->poll_fds = NULL;
|
375
|
+
rg_source->old_poll_fds = NULL;
|
376
|
+
|
377
|
+
return source;
|
378
|
+
}
|
379
|
+
|
380
|
+
static VALUE
|
381
|
+
ruby_source_set_priority (VALUE self, VALUE priority)
|
382
|
+
{
|
383
|
+
GSource *ruby_source = NULL;
|
384
|
+
|
385
|
+
if (ruby_source_id != 0)
|
386
|
+
ruby_source = g_main_context_find_source_by_id(NULL, ruby_source_id);
|
387
|
+
|
388
|
+
if (ruby_source)
|
389
|
+
g_source_set_priority(ruby_source, NUM2INT(priority));
|
390
|
+
|
391
|
+
return Qnil;
|
392
|
+
}
|
393
|
+
#endif
|
394
|
+
|
395
|
+
static VALUE
|
396
|
+
source_remove(self, tag)
|
397
|
+
VALUE self, tag;
|
398
|
+
{
|
399
|
+
VALUE callback;
|
400
|
+
callback = G_GET_RELATIVE(mGLibSource, id__callbacks__, tag);
|
401
|
+
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, tag);
|
402
|
+
g_hash_table_remove(callbacks_table, (gpointer)callback);
|
403
|
+
return CBOOL2RVAL(g_source_remove(NUM2UINT(tag)));
|
404
|
+
}
|
405
|
+
|
406
|
+
#if GLIB_CHECK_VERSION(2,12,0)
|
407
|
+
static VALUE
|
408
|
+
source_current_source(self)
|
409
|
+
VALUE self;
|
410
|
+
{
|
411
|
+
return BOXED2RVAL(g_main_current_source, G_TYPE_SOURCE);
|
412
|
+
}
|
413
|
+
#endif
|
414
|
+
|
415
|
+
static gboolean
|
416
|
+
invoke_source_func(data)
|
417
|
+
gpointer data;
|
418
|
+
{
|
419
|
+
callback_info_t *info = (callback_info_t *)data;
|
420
|
+
gboolean ret;
|
421
|
+
|
422
|
+
ret = RVAL2CBOOL(rb_funcall(info->callback, id_call, 0));
|
423
|
+
if (!ret)
|
424
|
+
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, UINT2NUM(info->id));
|
425
|
+
return ret;
|
426
|
+
}
|
427
|
+
|
428
|
+
|
429
|
+
/*****************************************/
|
430
|
+
GType
|
431
|
+
g_main_context_get_type(void)
|
432
|
+
{
|
433
|
+
static GType our_type = 0;
|
434
|
+
if (our_type == 0)
|
435
|
+
our_type = g_boxed_type_register_static ("GMainContext",
|
436
|
+
(GBoxedCopyFunc)g_main_context_ref,
|
437
|
+
(GBoxedFreeFunc)g_main_context_unref);
|
438
|
+
return our_type;
|
439
|
+
}
|
440
|
+
/*****************************************/
|
441
|
+
|
442
|
+
#define _SELF(s) ((GMainContext*)RVAL2BOXED(s, G_TYPE_MAIN_CONTEXT))
|
443
|
+
|
444
|
+
static VALUE
|
445
|
+
mc_initialize(self)
|
446
|
+
VALUE self;
|
447
|
+
{
|
448
|
+
GMainContext *context;
|
449
|
+
|
450
|
+
context = g_main_context_new();
|
451
|
+
|
452
|
+
g_main_context_set_poll_func(context, rg_poll);
|
453
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
454
|
+
{
|
455
|
+
GSource *source;
|
456
|
+
source = ruby_source_new();
|
457
|
+
g_source_attach(source, context);
|
458
|
+
g_source_unref(source);
|
459
|
+
}
|
460
|
+
#endif
|
461
|
+
|
462
|
+
G_INITIALIZE(self, context);
|
463
|
+
return Qnil;
|
464
|
+
}
|
465
|
+
|
466
|
+
static VALUE
|
467
|
+
mc_s_default(self)
|
468
|
+
VALUE self;
|
469
|
+
{
|
470
|
+
return BOXED2RVAL(g_main_context_default(), G_TYPE_MAIN_CONTEXT);
|
471
|
+
}
|
472
|
+
|
473
|
+
static VALUE
|
474
|
+
mc_iteration(self, may_block)
|
475
|
+
VALUE self, may_block;
|
476
|
+
{
|
477
|
+
return CBOOL2RVAL(g_main_context_iteration(_SELF(self), RVAL2CBOOL(may_block)));
|
478
|
+
}
|
479
|
+
|
480
|
+
static VALUE
|
481
|
+
mc_pending(self)
|
482
|
+
VALUE self;
|
483
|
+
{
|
484
|
+
return CBOOL2RVAL(g_main_context_pending(_SELF(self)));
|
485
|
+
}
|
486
|
+
|
487
|
+
static VALUE
|
488
|
+
mc_find_source(self, source_id)
|
489
|
+
VALUE self, source_id;
|
490
|
+
{
|
491
|
+
GSource* src = g_main_context_find_source_by_id(_SELF(self), NUM2UINT(source_id));
|
492
|
+
return BOXED2RVAL(src, G_TYPE_SOURCE);
|
493
|
+
}
|
494
|
+
|
495
|
+
/*
|
496
|
+
GSource* g_main_context_find_source_by_user_data
|
497
|
+
(GMainContext *context,
|
498
|
+
gpointer user_data);
|
499
|
+
GSource* g_main_context_find_source_by_funcs_user_data
|
500
|
+
(GMainContext *context,
|
501
|
+
GSourceFuncs *funcs,
|
502
|
+
gpointer user_data);
|
503
|
+
*/
|
504
|
+
|
505
|
+
static VALUE
|
506
|
+
mc_wakeup(self)
|
507
|
+
VALUE self;
|
508
|
+
{
|
509
|
+
g_main_context_wakeup(_SELF(self));
|
510
|
+
return self;
|
511
|
+
}
|
512
|
+
|
513
|
+
static VALUE
|
514
|
+
mc_acquire(self)
|
515
|
+
VALUE self;
|
516
|
+
{
|
517
|
+
return CBOOL2RVAL(g_main_context_acquire(_SELF(self)));
|
518
|
+
}
|
519
|
+
|
520
|
+
static VALUE
|
521
|
+
mc_release(self)
|
522
|
+
VALUE self;
|
523
|
+
{
|
524
|
+
g_main_context_release(_SELF(self));
|
525
|
+
return self;
|
526
|
+
}
|
527
|
+
|
528
|
+
#if GLIB_CHECK_VERSION(2,10,0)
|
529
|
+
static VALUE
|
530
|
+
mc_is_owner(self)
|
531
|
+
VALUE self;
|
532
|
+
{
|
533
|
+
return CBOOL2RVAL(g_main_context_is_owner(_SELF(self)));
|
534
|
+
}
|
535
|
+
#endif
|
536
|
+
|
537
|
+
/*
|
538
|
+
gboolean g_main_context_wait (GMainContext *context,
|
539
|
+
GCond *cond,
|
540
|
+
GMutex *mutex);
|
541
|
+
*/
|
542
|
+
|
543
|
+
static VALUE
|
544
|
+
mc_prepare(self)
|
545
|
+
VALUE self;
|
546
|
+
{
|
547
|
+
gint priority;
|
548
|
+
gboolean ret = g_main_context_prepare(_SELF(self), &priority);
|
549
|
+
|
550
|
+
return rb_assoc_new(CBOOL2RVAL(ret), INT2NUM(priority));
|
551
|
+
}
|
552
|
+
|
553
|
+
static VALUE
|
554
|
+
mc_query(self, max_priority)
|
555
|
+
VALUE self, max_priority;
|
556
|
+
{
|
557
|
+
gint i, timeout_;
|
558
|
+
VALUE ary;
|
559
|
+
|
560
|
+
GPollFD* fds = g_new (GPollFD, 100);
|
561
|
+
gint ret = g_main_context_query(_SELF(self), NUM2INT(max_priority),
|
562
|
+
&timeout_, fds, 100);
|
563
|
+
if (ret > 100) {
|
564
|
+
g_free(fds);
|
565
|
+
fds = g_new(GPollFD, ret);
|
566
|
+
g_main_context_query(_SELF(self), NUM2INT(max_priority),
|
567
|
+
&timeout_, fds, ret);
|
568
|
+
}
|
569
|
+
|
570
|
+
ary = rb_ary_new();
|
571
|
+
for (i = 0; i < ret; i++)
|
572
|
+
rb_ary_push(ary, BOXED2RVAL(&fds[i], G_TYPE_POLL_FD));
|
573
|
+
|
574
|
+
g_free(fds);
|
575
|
+
return rb_assoc_new(INT2NUM(timeout_), ary);
|
576
|
+
}
|
577
|
+
|
578
|
+
/* How can I implement this?
|
579
|
+
static VALUE
|
580
|
+
mc_check(self, max_priority)
|
581
|
+
VALUE self, max_priority;
|
582
|
+
{
|
583
|
+
gint i, timeout_;
|
584
|
+
VALUE ary;
|
585
|
+
|
586
|
+
GPollFD* fds;
|
587
|
+
gint ret, n_fds;
|
588
|
+
|
589
|
+
fds = g_new (GPollFD, 10);
|
590
|
+
n_fds = g_main_context_query(_SELF(self), NUM2INT(max_priority),
|
591
|
+
&timeout_, fds, 10);
|
592
|
+
printf("n_fds = %d\n", n_fds);
|
593
|
+
|
594
|
+
g_free(fds);
|
595
|
+
fds = g_new (GPollFD, n_fds);
|
596
|
+
|
597
|
+
ret = g_main_context_check(_SELF(self), NUM2INT(max_priority),
|
598
|
+
fds, n_fds);
|
599
|
+
printf("ret = %d\n", ret);
|
600
|
+
ary = rb_ary_new();
|
601
|
+
for (i = 0; i < ret; i++)
|
602
|
+
rb_ary_push(ary, BOXED2RVAL(&fds[i], G_TYPE_POLL_FD));
|
603
|
+
|
604
|
+
g_free(fds);
|
605
|
+
return ary;
|
606
|
+
}
|
607
|
+
*/
|
608
|
+
|
609
|
+
static VALUE
|
610
|
+
mc_dispatch(self)
|
611
|
+
VALUE self;
|
612
|
+
{
|
613
|
+
g_main_context_dispatch(_SELF(self));
|
614
|
+
return self;
|
615
|
+
}
|
616
|
+
|
617
|
+
/* How can I get "self" or something like it as key ....
|
618
|
+
static gint
|
619
|
+
poll_func(ufds, nfsd, timeout_)
|
620
|
+
GPollFD* ufds;
|
621
|
+
guint nfsd;
|
622
|
+
gint timeout_;
|
623
|
+
{
|
624
|
+
VALUE func = rb_ivar_get(self, id_poll_func);
|
625
|
+
if NIL_P(func) return -1;
|
626
|
+
|
627
|
+
return INT2NUM(rb_funcall(func, 3, BOXED2RVAL(ufds, G_TYPE_POLL_FD),
|
628
|
+
UINT2NUM(nfsd), INT2NUM(timeout_)));
|
629
|
+
}
|
630
|
+
|
631
|
+
static VALUE
|
632
|
+
mc_set_poll_func(self)
|
633
|
+
VALUE self;
|
634
|
+
{
|
635
|
+
rb_ivar_set(self, id_poll_func, rb_block_proc());
|
636
|
+
g_main_context_set_poll_func(_SELF(self), (GPollFunc)poll_func);
|
637
|
+
|
638
|
+
return self;
|
639
|
+
}
|
640
|
+
*/
|
641
|
+
|
642
|
+
/*
|
643
|
+
GPollFunc g_main_context_get_poll_func (GMainContext *context);
|
644
|
+
*/
|
645
|
+
|
646
|
+
static VALUE
|
647
|
+
mc_add_poll(self, fd, priority)
|
648
|
+
VALUE self, fd, priority;
|
649
|
+
{
|
650
|
+
g_main_context_add_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD),
|
651
|
+
NUM2INT(priority));
|
652
|
+
return self;
|
653
|
+
}
|
654
|
+
|
655
|
+
static VALUE
|
656
|
+
mc_remove_poll(self, fd)
|
657
|
+
VALUE self, fd;
|
658
|
+
{
|
659
|
+
g_main_context_remove_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD));
|
660
|
+
return self;
|
661
|
+
}
|
662
|
+
|
663
|
+
#ifdef HAVE_G_MAIN_DEPTH
|
664
|
+
static VALUE
|
665
|
+
mc_s_depth(self)
|
666
|
+
VALUE self;
|
667
|
+
{
|
668
|
+
return INT2NUM(g_main_depth());
|
669
|
+
}
|
670
|
+
#endif
|
671
|
+
|
672
|
+
|
673
|
+
static VALUE
|
674
|
+
timeout_source_new(self, interval)
|
675
|
+
VALUE self, interval;
|
676
|
+
{
|
677
|
+
return BOXED2RVAL(g_timeout_source_new(NUM2UINT(interval)), G_TYPE_SOURCE);
|
678
|
+
}
|
679
|
+
#if GLIB_CHECK_VERSION(2,14,0)
|
680
|
+
static VALUE
|
681
|
+
timeout_source_new_seconds(self, interval)
|
682
|
+
VALUE self, interval;
|
683
|
+
{
|
684
|
+
return BOXED2RVAL(g_timeout_source_new_seconds(NUM2UINT(interval)), G_TYPE_SOURCE);
|
685
|
+
}
|
686
|
+
#endif
|
687
|
+
|
688
|
+
static VALUE
|
689
|
+
timeout_add(int argc, VALUE *argv, VALUE self)
|
690
|
+
{
|
691
|
+
VALUE interval, rb_priority, func, rb_id;
|
692
|
+
gint priority;
|
693
|
+
callback_info_t *info;
|
694
|
+
guint id;
|
695
|
+
|
696
|
+
rb_scan_args(argc, argv, "11&", &interval, &rb_priority, &func);
|
697
|
+
|
698
|
+
priority = NIL_P(rb_priority) ? G_PRIORITY_DEFAULT : NUM2INT(rb_priority);
|
699
|
+
info = ALLOC(callback_info_t);
|
700
|
+
info->callback = func;
|
701
|
+
id = g_timeout_add_full(priority, NUM2UINT(interval),
|
702
|
+
(GSourceFunc)invoke_source_func,
|
703
|
+
(gpointer)info, g_free);
|
704
|
+
info->id = id;
|
705
|
+
rb_id = UINT2NUM(id);
|
706
|
+
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
|
707
|
+
g_hash_table_insert(callbacks_table, (gpointer)func, info);
|
708
|
+
return rb_id;
|
709
|
+
}
|
710
|
+
|
711
|
+
#if GLIB_CHECK_VERSION(2,14,0)
|
712
|
+
static VALUE
|
713
|
+
timeout_add_seconds(int argc, VALUE *argv, VALUE self)
|
714
|
+
{
|
715
|
+
VALUE interval, rb_priority, func, rb_id;
|
716
|
+
gint priority;
|
717
|
+
callback_info_t *info;
|
718
|
+
guint id;
|
719
|
+
|
720
|
+
rb_scan_args(argc, argv, "11&", &interval, &rb_priority, &func);
|
721
|
+
|
722
|
+
priority = NIL_P(rb_priority) ? G_PRIORITY_DEFAULT : NUM2INT(rb_priority);
|
723
|
+
info = ALLOC(callback_info_t);
|
724
|
+
info->callback = func;
|
725
|
+
id = g_timeout_add_seconds_full(priority,
|
726
|
+
NUM2UINT(interval),
|
727
|
+
(GSourceFunc)invoke_source_func,
|
728
|
+
(gpointer)info,
|
729
|
+
g_free);
|
730
|
+
info->id = id;
|
731
|
+
rb_id = UINT2NUM(id);
|
732
|
+
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
|
733
|
+
g_hash_table_insert(callbacks_table, (gpointer)func, info);
|
734
|
+
return rb_id;
|
735
|
+
}
|
736
|
+
#endif
|
737
|
+
|
738
|
+
static VALUE
|
739
|
+
idle_source_new(self)
|
740
|
+
VALUE self;
|
741
|
+
{
|
742
|
+
return BOXED2RVAL(g_idle_source_new(), G_TYPE_SOURCE);
|
743
|
+
}
|
744
|
+
|
745
|
+
static VALUE
|
746
|
+
idle_add(argc, argv, self)
|
747
|
+
gint argc;
|
748
|
+
VALUE* argv;
|
749
|
+
VALUE self;
|
750
|
+
{
|
751
|
+
VALUE arg1, arg2, func, rb_id;
|
752
|
+
callback_info_t *info;
|
753
|
+
guint id;
|
754
|
+
gint priority;
|
755
|
+
|
756
|
+
rb_scan_args(argc, argv, "02", &arg1, &arg2);
|
757
|
+
|
758
|
+
if (RVAL2CBOOL(rb_obj_is_kind_of(arg1, rb_cProc))) {
|
759
|
+
priority = G_PRIORITY_DEFAULT;
|
760
|
+
func = arg1;
|
761
|
+
} else if (RVAL2CBOOL(rb_obj_is_kind_of(arg1, rb_cInteger))) {
|
762
|
+
priority = NUM2INT(arg1);
|
763
|
+
func = rb_block_proc();
|
764
|
+
} else {
|
765
|
+
priority = G_PRIORITY_DEFAULT;
|
766
|
+
func = rb_block_proc();
|
767
|
+
}
|
768
|
+
|
769
|
+
info = ALLOC(callback_info_t);
|
770
|
+
info->callback = func;
|
771
|
+
id = g_idle_add_full(priority, (GSourceFunc)invoke_source_func,
|
772
|
+
(gpointer)info, g_free);
|
773
|
+
info->id = id;
|
774
|
+
rb_id = UINT2NUM(id);
|
775
|
+
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
|
776
|
+
g_hash_table_insert(callbacks_table, (gpointer)func, info);
|
777
|
+
return rb_id;
|
778
|
+
}
|
779
|
+
|
780
|
+
static VALUE
|
781
|
+
idle_remove(self, func)
|
782
|
+
VALUE self, func;
|
783
|
+
{
|
784
|
+
callback_info_t *info;
|
785
|
+
|
786
|
+
info = g_hash_table_lookup(callbacks_table, (gpointer)func);
|
787
|
+
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, UINT2NUM(info->id));
|
788
|
+
g_hash_table_remove(callbacks_table, (gpointer)func);
|
789
|
+
return CBOOL2RVAL(g_idle_remove_by_data((gpointer)info));
|
790
|
+
}
|
791
|
+
|
792
|
+
#if GLIB_CHECK_VERSION(2,4,0)
|
793
|
+
static VALUE
|
794
|
+
child_watch_source_new(self, pid)
|
795
|
+
VALUE self, pid;
|
796
|
+
{
|
797
|
+
return BOXED2RVAL(g_child_watch_source_new((GPid)NUM2INT(pid)), G_TYPE_SOURCE);
|
798
|
+
}
|
799
|
+
|
800
|
+
static void
|
801
|
+
child_watch_func(pid, status, func)
|
802
|
+
GPid pid;
|
803
|
+
gint status;
|
804
|
+
gpointer func;
|
805
|
+
{
|
806
|
+
rb_funcall((VALUE)func, id_call, 2, INT2NUM((long)pid), INT2NUM(status));
|
807
|
+
}
|
808
|
+
|
809
|
+
static VALUE
|
810
|
+
child_watch_add(self, pid)
|
811
|
+
VALUE self, pid;
|
812
|
+
{
|
813
|
+
VALUE func = rb_block_proc();
|
814
|
+
G_RELATIVE(self, func);
|
815
|
+
return UINT2NUM(g_child_watch_add((GPid)NUM2INT(pid),
|
816
|
+
(GChildWatchFunc)child_watch_func, (gpointer)func));
|
817
|
+
}
|
818
|
+
#endif
|
819
|
+
|
820
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
821
|
+
static void
|
822
|
+
ruby_source_remove(VALUE data)
|
823
|
+
{
|
824
|
+
if (ruby_source_id != 0) {
|
825
|
+
g_source_remove(ruby_source_id);
|
826
|
+
ruby_source_id = 0;
|
827
|
+
}
|
828
|
+
}
|
829
|
+
#endif
|
830
|
+
|
831
|
+
void
|
832
|
+
Init_glib_main_context()
|
833
|
+
{
|
834
|
+
VALUE mc = G_DEF_CLASS(G_TYPE_MAIN_CONTEXT, "MainContext", mGLib);
|
835
|
+
|
836
|
+
VALUE timeout = rb_define_module_under(mGLib, "Timeout");
|
837
|
+
VALUE idle = rb_define_module_under(mGLib, "Idle");
|
838
|
+
#if GLIB_CHECK_VERSION(2,4,0)
|
839
|
+
VALUE child_watch = rb_define_module_under(mGLib, "ChildWatch");
|
840
|
+
#endif
|
841
|
+
|
842
|
+
id_call = rb_intern("call");
|
843
|
+
id__callbacks__ = rb_intern("__callbacks__");
|
844
|
+
callbacks_table = g_hash_table_new(NULL, NULL);
|
845
|
+
|
846
|
+
rb_define_singleton_method(mGLib, "set_ruby_thread_priority",
|
847
|
+
ruby_source_set_priority, 1);
|
848
|
+
rb_define_singleton_method(mGLib, "ruby_thread_priority=",
|
849
|
+
ruby_source_set_priority, 1);
|
850
|
+
|
851
|
+
mGLibSource = rb_const_get(mGLib, rb_intern("Source"));
|
852
|
+
rb_define_singleton_method(mGLibSource, "remove", source_remove, 1);
|
853
|
+
#if GLIB_CHECK_VERSION(2,12,0)
|
854
|
+
rb_define_singleton_method(mGLibSource, "current", source_current_source, 0);
|
855
|
+
#endif
|
856
|
+
/*
|
857
|
+
id_poll_func = rb_intern("__poll_func__");
|
858
|
+
*/
|
859
|
+
rb_define_method(mc, "initialize", mc_initialize, 0);
|
860
|
+
rb_define_singleton_method(mc, "default", mc_s_default, 0);
|
861
|
+
rb_define_method(mc, "iteration", mc_iteration, 1);
|
862
|
+
rb_define_method(mc, "pending?", mc_pending, 0);
|
863
|
+
rb_define_method(mc, "find_source", mc_find_source, 1);
|
864
|
+
rb_define_method(mc, "wakeup", mc_wakeup, 0);
|
865
|
+
rb_define_method(mc, "acquire", mc_acquire, 0);
|
866
|
+
rb_define_method(mc, "release", mc_release, 0);
|
867
|
+
#if GLIB_CHECK_VERSION(2,10,0)
|
868
|
+
rb_define_method(mc, "owner?", mc_is_owner, 0);
|
869
|
+
#endif
|
870
|
+
rb_define_method(mc, "prepare", mc_prepare, 0);
|
871
|
+
rb_define_method(mc, "query", mc_query, 1);
|
872
|
+
/*
|
873
|
+
rb_define_method(mc, "check", mc_check, 1);
|
874
|
+
*/
|
875
|
+
rb_define_method(mc, "dispatch", mc_dispatch, 0);
|
876
|
+
/*
|
877
|
+
rb_define_method(mc, "set_poll_func", mc_set_poll_func, 0);
|
878
|
+
*/
|
879
|
+
rb_define_method(mc, "add_poll", mc_add_poll, 2);
|
880
|
+
rb_define_method(mc, "remove_poll", mc_remove_poll, 1);
|
881
|
+
#ifdef HAVE_G_MAIN_DEPTH
|
882
|
+
rb_define_singleton_method(mc, "depth", mc_s_depth, 0);
|
883
|
+
#endif
|
884
|
+
rb_define_module_function(timeout, "source_new", timeout_source_new, 1);
|
885
|
+
#if GLIB_CHECK_VERSION(2,14,0)
|
886
|
+
rb_define_module_function(timeout, "source_new_seconds", timeout_source_new_seconds, 1);
|
887
|
+
#endif
|
888
|
+
rb_define_module_function(timeout, "add", timeout_add, -1);
|
889
|
+
#if GLIB_CHECK_VERSION(2,14,0)
|
890
|
+
rb_define_module_function(timeout, "add_seconds", timeout_add_seconds, -1);
|
891
|
+
#endif
|
892
|
+
rb_define_module_function(idle, "source_new", idle_source_new, 0);
|
893
|
+
rb_define_module_function(idle, "add", idle_add, -1);
|
894
|
+
rb_define_module_function(idle, "remove", idle_remove, 1);
|
895
|
+
|
896
|
+
#if GLIB_CHECK_VERSION(2,4,0)
|
897
|
+
rb_define_module_function(child_watch, "source_new", child_watch_source_new, 1);
|
898
|
+
rb_define_module_function(child_watch, "add", child_watch_add, 1);
|
899
|
+
#endif
|
900
|
+
|
901
|
+
|
902
|
+
default_poll_func = g_main_context_get_poll_func(NULL);
|
903
|
+
g_main_context_set_poll_func(NULL, rg_poll);
|
904
|
+
rb_set_end_proc(restore_poll_func, Qnil);
|
905
|
+
|
906
|
+
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
907
|
+
{
|
908
|
+
GSource *source;
|
909
|
+
|
910
|
+
source = ruby_source_new();
|
911
|
+
g_source_set_priority(source, G_PRIORITY_DEFAULT_IDLE);
|
912
|
+
ruby_source_id = g_source_attach(source, NULL);
|
913
|
+
g_source_unref(source);
|
914
|
+
rb_set_end_proc(ruby_source_remove, Qnil);
|
915
|
+
}
|
916
|
+
#endif
|
917
|
+
}
|