glib2 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }