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.
Files changed (86) hide show
  1. data/ChangeLog +3023 -0
  2. data/README +28 -0
  3. data/Rakefile +87 -0
  4. data/extconf.rb +61 -0
  5. data/sample/bookmarkfile.rb +66 -0
  6. data/sample/completion.rb +45 -0
  7. data/sample/idle.rb +41 -0
  8. data/sample/iochannel.rb +44 -0
  9. data/sample/keyfile.rb +62 -0
  10. data/sample/shell.rb +36 -0
  11. data/sample/spawn.rb +25 -0
  12. data/sample/timeout.rb +28 -0
  13. data/sample/timeout2.rb +35 -0
  14. data/sample/timer.rb +40 -0
  15. data/sample/type-register.rb +103 -0
  16. data/sample/type-register2.rb +104 -0
  17. data/sample/utils.rb +54 -0
  18. data/src/glib-enum-types.c +1032 -0
  19. data/src/glib-enum-types.h +140 -0
  20. data/src/lib/glib-mkenums.rb +199 -0
  21. data/src/lib/glib2.rb +220 -0
  22. data/src/lib/mkmf-gnome2.rb +390 -0
  23. data/src/lib/pkg-config.rb +137 -0
  24. data/src/rbgcompat.h +30 -0
  25. data/src/rbglib.c +320 -0
  26. data/src/rbglib.h +96 -0
  27. data/src/rbglib_bookmarkfile.c +595 -0
  28. data/src/rbglib_completion.c +192 -0
  29. data/src/rbglib_convert.c +195 -0
  30. data/src/rbglib_error.c +95 -0
  31. data/src/rbglib_fileutils.c +83 -0
  32. data/src/rbglib_i18n.c +44 -0
  33. data/src/rbglib_int64.c +157 -0
  34. data/src/rbglib_iochannel.c +883 -0
  35. data/src/rbglib_keyfile.c +846 -0
  36. data/src/rbglib_maincontext.c +917 -0
  37. data/src/rbglib_mainloop.c +87 -0
  38. data/src/rbglib_messages.c +150 -0
  39. data/src/rbglib_pollfd.c +111 -0
  40. data/src/rbglib_shell.c +68 -0
  41. data/src/rbglib_source.c +190 -0
  42. data/src/rbglib_spawn.c +345 -0
  43. data/src/rbglib_threads.c +51 -0
  44. data/src/rbglib_timer.c +127 -0
  45. data/src/rbglib_unicode.c +611 -0
  46. data/src/rbglib_utils.c +386 -0
  47. data/src/rbglib_win32.c +136 -0
  48. data/src/rbgobj_boxed.c +251 -0
  49. data/src/rbgobj_closure.c +337 -0
  50. data/src/rbgobj_convert.c +167 -0
  51. data/src/rbgobj_enums.c +961 -0
  52. data/src/rbgobj_fundamental.c +30 -0
  53. data/src/rbgobj_object.c +892 -0
  54. data/src/rbgobj_param.c +390 -0
  55. data/src/rbgobj_paramspecs.c +305 -0
  56. data/src/rbgobj_signal.c +963 -0
  57. data/src/rbgobj_strv.c +61 -0
  58. data/src/rbgobj_type.c +851 -0
  59. data/src/rbgobj_typeinstance.c +121 -0
  60. data/src/rbgobj_typeinterface.c +148 -0
  61. data/src/rbgobj_typemodule.c +66 -0
  62. data/src/rbgobj_typeplugin.c +49 -0
  63. data/src/rbgobj_value.c +313 -0
  64. data/src/rbgobj_valuearray.c +59 -0
  65. data/src/rbgobj_valuetypes.c +298 -0
  66. data/src/rbgobject.c +406 -0
  67. data/src/rbgobject.h +265 -0
  68. data/src/rbgprivate.h +88 -0
  69. data/src/rbgutil.c +222 -0
  70. data/src/rbgutil.h +82 -0
  71. data/src/rbgutil_callback.c +231 -0
  72. data/test/glib-test-init.rb +6 -0
  73. data/test/glib-test-utils.rb +12 -0
  74. data/test/run-test.rb +25 -0
  75. data/test/test_enum.rb +99 -0
  76. data/test/test_file_utils.rb +15 -0
  77. data/test/test_glib2.rb +120 -0
  78. data/test/test_iochannel.rb +275 -0
  79. data/test/test_key_file.rb +38 -0
  80. data/test/test_mkenums.rb +25 -0
  81. data/test/test_signal.rb +20 -0
  82. data/test/test_timeout.rb +28 -0
  83. data/test/test_unicode.rb +369 -0
  84. data/test/test_utils.rb +37 -0
  85. data/test/test_win32.rb +13 -0
  86. 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
+ }