cool.io 1.2.0-x86-mswin32-60

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 (79) hide show
  1. data/.gitignore +26 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +5 -0
  4. data/CHANGES.md +177 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +20 -0
  7. data/README.md +172 -0
  8. data/Rakefile +81 -0
  9. data/cool.io.gemspec +28 -0
  10. data/examples/dslified_echo_client.rb +34 -0
  11. data/examples/dslified_echo_server.rb +24 -0
  12. data/examples/echo_client.rb +38 -0
  13. data/examples/echo_server.rb +27 -0
  14. data/examples/google.rb +9 -0
  15. data/examples/httpclient.rb +38 -0
  16. data/ext/cool.io/.gitignore +5 -0
  17. data/ext/cool.io/cool.io.h +58 -0
  18. data/ext/cool.io/cool.io_ext.c +25 -0
  19. data/ext/cool.io/ev_wrap.h +8 -0
  20. data/ext/cool.io/extconf.rb +73 -0
  21. data/ext/cool.io/iowatcher.c +189 -0
  22. data/ext/cool.io/libev.c +8 -0
  23. data/ext/cool.io/loop.c +301 -0
  24. data/ext/cool.io/stat_watcher.c +269 -0
  25. data/ext/cool.io/timer_watcher.c +219 -0
  26. data/ext/cool.io/utils.c +122 -0
  27. data/ext/cool.io/watcher.c +264 -0
  28. data/ext/cool.io/watcher.h +71 -0
  29. data/ext/http11_client/.gitignore +5 -0
  30. data/ext/http11_client/LICENSE +31 -0
  31. data/ext/http11_client/ext_help.h +14 -0
  32. data/ext/http11_client/extconf.rb +6 -0
  33. data/ext/http11_client/http11_client.c +300 -0
  34. data/ext/http11_client/http11_parser.c +403 -0
  35. data/ext/http11_client/http11_parser.h +48 -0
  36. data/ext/http11_client/http11_parser.rl +173 -0
  37. data/ext/iobuffer/extconf.rb +9 -0
  38. data/ext/iobuffer/iobuffer.c +765 -0
  39. data/ext/libev/Changes +388 -0
  40. data/ext/libev/LICENSE +36 -0
  41. data/ext/libev/README +58 -0
  42. data/ext/libev/README.embed +3 -0
  43. data/ext/libev/ev.c +4803 -0
  44. data/ext/libev/ev.h +845 -0
  45. data/ext/libev/ev_epoll.c +279 -0
  46. data/ext/libev/ev_kqueue.c +214 -0
  47. data/ext/libev/ev_poll.c +148 -0
  48. data/ext/libev/ev_port.c +185 -0
  49. data/ext/libev/ev_select.c +314 -0
  50. data/ext/libev/ev_vars.h +203 -0
  51. data/ext/libev/ev_win32.c +163 -0
  52. data/ext/libev/ev_wrap.h +200 -0
  53. data/ext/libev/test_libev_win32.c +123 -0
  54. data/lib/.gitignore +2 -0
  55. data/lib/cool.io.rb +32 -0
  56. data/lib/cool.io/async_watcher.rb +43 -0
  57. data/lib/cool.io/custom_require.rb +9 -0
  58. data/lib/cool.io/dns_resolver.rb +225 -0
  59. data/lib/cool.io/dsl.rb +135 -0
  60. data/lib/cool.io/eventmachine.rb +234 -0
  61. data/lib/cool.io/http_client.rb +427 -0
  62. data/lib/cool.io/io.rb +174 -0
  63. data/lib/cool.io/iowatcher.rb +17 -0
  64. data/lib/cool.io/listener.rb +93 -0
  65. data/lib/cool.io/loop.rb +130 -0
  66. data/lib/cool.io/meta.rb +49 -0
  67. data/lib/cool.io/server.rb +74 -0
  68. data/lib/cool.io/socket.rb +230 -0
  69. data/lib/cool.io/timer_watcher.rb +17 -0
  70. data/lib/cool.io/version.rb +5 -0
  71. data/lib/coolio.rb +2 -0
  72. data/spec/async_watcher_spec.rb +57 -0
  73. data/spec/dns_spec.rb +39 -0
  74. data/spec/spec_helper.rb +12 -0
  75. data/spec/stat_watcher_spec.rb +77 -0
  76. data/spec/timer_watcher_spec.rb +55 -0
  77. data/spec/unix_listener_spec.rb +25 -0
  78. data/spec/unix_server_spec.rb +25 -0
  79. metadata +200 -0
@@ -0,0 +1,219 @@
1
+ /*
2
+ * Copyright (C) 2007 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+ #include "ruby.h"
8
+ #include "ev_wrap.h"
9
+
10
+ #include "cool.io.h"
11
+ #include "watcher.h"
12
+
13
+ static VALUE mCoolio = Qnil;
14
+ static VALUE cCoolio_Watcher = Qnil;
15
+ static VALUE cCoolio_TimerWatcher = Qnil;
16
+ static VALUE cCoolio_Loop = Qnil;
17
+
18
+ static VALUE Coolio_TimerWatcher_initialize(int argc, VALUE *argv, VALUE self);
19
+ static VALUE Coolio_TimerWatcher_attach(VALUE self, VALUE loop);
20
+ static VALUE Coolio_TimerWatcher_detach(VALUE self);
21
+ static VALUE Coolio_TimerWatcher_enable(VALUE self);
22
+ static VALUE Coolio_TimerWatcher_disable(VALUE self);
23
+ static VALUE Coolio_TimerWatcher_reset(VALUE self);
24
+ static VALUE Coolio_TimerWatcher_on_timer(VALUE self);
25
+
26
+ static void Coolio_TimerWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
27
+ static void Coolio_TimerWatcher_dispatch_callback(VALUE self, int revents);
28
+
29
+ /*
30
+ * Coolio::TimerWatcher lets you create either one-shot or periodic timers which
31
+ * run within Coolio's event loop. It's useful for creating timeouts or
32
+ * events which fire periodically.
33
+ */
34
+ void Init_coolio_timer_watcher()
35
+ {
36
+ mCoolio = rb_define_module("Coolio");
37
+ cCoolio_Watcher = rb_define_class_under(mCoolio, "Watcher", rb_cObject);
38
+ cCoolio_TimerWatcher = rb_define_class_under(mCoolio, "TimerWatcher", cCoolio_Watcher);
39
+ cCoolio_Loop = rb_define_class_under(mCoolio, "Loop", rb_cObject);
40
+
41
+ rb_define_method(cCoolio_TimerWatcher, "initialize", Coolio_TimerWatcher_initialize, -1);
42
+ rb_define_method(cCoolio_TimerWatcher, "attach", Coolio_TimerWatcher_attach, 1);
43
+ rb_define_method(cCoolio_TimerWatcher, "detach", Coolio_TimerWatcher_detach, 0);
44
+ rb_define_method(cCoolio_TimerWatcher, "enable", Coolio_TimerWatcher_enable, 0);
45
+ rb_define_method(cCoolio_TimerWatcher, "disable", Coolio_TimerWatcher_disable, 0);
46
+ rb_define_method(cCoolio_TimerWatcher, "reset", Coolio_TimerWatcher_reset, 0);
47
+ rb_define_method(cCoolio_TimerWatcher, "on_timer", Coolio_TimerWatcher_on_timer, 0);
48
+ }
49
+
50
+ /**
51
+ * call-seq:
52
+ * Coolio::TimerWatcher.initialize(interval, repeating = false) -> Coolio::TimerWatcher
53
+ *
54
+ * Create a new Coolio::TimerWatcher for the given IO object and add it to the
55
+ * given Coolio::Loop. Interval defines a duration in seconds to wait for events,
56
+ * and can be specified as an Integer or Float. Repeating is a boolean
57
+ * indicating whether the timer is one shot or should fire on the given
58
+ * interval.
59
+ */
60
+ static VALUE Coolio_TimerWatcher_initialize(int argc, VALUE *argv, VALUE self)
61
+ {
62
+ VALUE interval, repeating;
63
+ struct Coolio_Watcher *watcher_data;
64
+
65
+ rb_scan_args(argc, argv, "11", &interval, &repeating);
66
+ interval = rb_convert_type(interval, T_FLOAT, "Float", "to_f");
67
+
68
+ rb_iv_set(self, "@interval", interval);
69
+ rb_iv_set(self, "@repeating", repeating);
70
+
71
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
72
+
73
+ watcher_data->dispatch_callback = Coolio_TimerWatcher_dispatch_callback;
74
+ ev_timer_init(
75
+ &watcher_data->event_types.ev_timer,
76
+ Coolio_TimerWatcher_libev_callback,
77
+ NUM2DBL(interval),
78
+ repeating == Qtrue ? NUM2DBL(interval) : 0
79
+ );
80
+ watcher_data->event_types.ev_timer.data = (void *)self;
81
+
82
+ return Qnil;
83
+ }
84
+
85
+ /**
86
+ * call-seq:
87
+ * Coolio::TimerWatcher.attach(loop) -> Coolio::TimerWatcher
88
+ *
89
+ * Attach the timer watcher to the given Coolio::Loop. If the watcher is already
90
+ * attached to a loop, detach it from the old one and attach it to the new one.
91
+ */
92
+ static VALUE Coolio_TimerWatcher_attach(VALUE self, VALUE loop)
93
+ {
94
+ ev_tstamp interval, timeout;
95
+ struct Coolio_Loop *loop_data;
96
+ struct Coolio_Watcher *watcher_data;
97
+
98
+ if(!rb_obj_is_kind_of(loop, cCoolio_Loop))
99
+ rb_raise(rb_eArgError, "expected loop to be an instance of Coolio::Loop");
100
+
101
+ Data_Get_Struct(loop, struct Coolio_Loop, loop_data);
102
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
103
+
104
+ if(watcher_data->loop != Qnil)
105
+ Coolio_TimerWatcher_detach(self);
106
+
107
+ watcher_data->loop = loop;
108
+
109
+ /* Calibrate timeout to account for potential drift */
110
+ interval = NUM2DBL(rb_iv_get(self, "@interval"));
111
+ timeout = interval + ev_time() - ev_now(loop_data->ev_loop);
112
+
113
+ ev_timer_set(
114
+ &watcher_data->event_types.ev_timer,
115
+ timeout,
116
+ rb_iv_get(self, "@repeating") == Qtrue ? interval : 0
117
+ );
118
+
119
+ ev_timer_start(loop_data->ev_loop, &watcher_data->event_types.ev_timer);
120
+ rb_call_super(1, &loop);
121
+
122
+ return self;
123
+ }
124
+
125
+ /**
126
+ * call-seq:
127
+ * Coolio::TimerWatcher.detach -> Coolio::TimerWatcher
128
+ *
129
+ * Detach the timer watcher from its current Coolio::Loop.
130
+ */
131
+ static VALUE Coolio_TimerWatcher_detach(VALUE self)
132
+ {
133
+ Watcher_Detach(timer, self);
134
+
135
+ return self;
136
+ }
137
+
138
+ /**
139
+ * call-seq:
140
+ * Coolio::TimerWatcher.enable -> Coolio::TimerWatcher
141
+ *
142
+ * Re-enable a timer watcher which has been temporarily disabled. See the
143
+ * disable method for a more thorough explanation.
144
+ */
145
+ static VALUE Coolio_TimerWatcher_enable(VALUE self)
146
+ {
147
+ Watcher_Enable(timer, self);
148
+
149
+ return self;
150
+ }
151
+
152
+ /**
153
+ * call-seq:
154
+ * Coolio::TimerWatcher.disable -> Coolio::TimerWatcher
155
+ *
156
+ * Temporarily disable a timer watcher which is attached to a loop.
157
+ * This is useful if you wish to toggle event monitoring on and off.
158
+ */
159
+ static VALUE Coolio_TimerWatcher_disable(VALUE self)
160
+ {
161
+ Watcher_Disable(timer, self);
162
+
163
+ return self;
164
+ }
165
+
166
+ /**
167
+ * call-seq:
168
+ * Coolio::TimerWatcher#reset -> Coolio::TimerWatcher
169
+ *
170
+ * Reset the TimerWatcher. This behaves differently depending on if it's repeating.
171
+ *
172
+ * If the timer is pending, its pending status is cleared.
173
+ *
174
+ * If the timer is attached but nonrepeating, stop it (as if it timed out)
175
+ *
176
+ * If the timer is repeating, reset it so it will fire again after its given interval
177
+ */
178
+ static VALUE Coolio_TimerWatcher_reset(VALUE self)
179
+ {
180
+ struct Coolio_Watcher *watcher_data;
181
+ struct Coolio_Loop *loop_data;
182
+
183
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
184
+
185
+ if(watcher_data->loop == Qnil)
186
+ rb_raise(rb_eRuntimeError, "not attached to a loop");
187
+
188
+ Data_Get_Struct(watcher_data->loop, struct Coolio_Loop, loop_data);
189
+
190
+ ev_timer_again(loop_data->ev_loop, &watcher_data->event_types.ev_timer);
191
+
192
+ return self;
193
+ }
194
+
195
+ /**
196
+ * call-seq:
197
+ * Coolio::TimerWatcher#on_timer -> nil
198
+ *
199
+ * Called whenever the TimerWatcher fires
200
+ */
201
+ static VALUE Coolio_TimerWatcher_on_timer(VALUE self)
202
+ {
203
+ return Qnil;
204
+ }
205
+
206
+ /* libev callback */
207
+ static void Coolio_TimerWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents)
208
+ {
209
+ Coolio_Loop_process_event((VALUE)timer->data, revents);
210
+ }
211
+
212
+ /* Coolio::Loop dispatch callback */
213
+ static void Coolio_TimerWatcher_dispatch_callback(VALUE self, int revents)
214
+ {
215
+ if(revents & EV_TIMEOUT)
216
+ rb_funcall(self, rb_intern("on_timer"), 0, 0);
217
+ else
218
+ rb_raise(rb_eRuntimeError, "unknown revents value for ev_timer: %d", revents);
219
+ }
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Copyright (C) 2007 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+ #include "ruby.h"
8
+
9
+ #ifdef HAVE_SYS_RESOURCE_H
10
+ #include <sys/resource.h>
11
+ #endif
12
+
13
+ #ifdef HAVE_SYS_SYSCTL_H
14
+ #include <sys/param.h>
15
+ #include <sys/sysctl.h>
16
+ #endif
17
+
18
+ static VALUE mCoolio = Qnil;
19
+ static VALUE cCoolio_Utils = Qnil;
20
+
21
+ static VALUE Coolio_Utils_ncpus(VALUE self);
22
+ static VALUE Coolio_Utils_maxfds(VALUE self);
23
+ static VALUE Coolio_Utils_setmaxfds(VALUE self, VALUE max);
24
+
25
+ /*
26
+ * Assorted utility routines
27
+ */
28
+ void Init_coolio_utils()
29
+ {
30
+ mCoolio = rb_define_module("Coolio");
31
+ cCoolio_Utils = rb_define_module_under(mCoolio, "Utils");
32
+
33
+ rb_define_singleton_method(cCoolio_Utils, "ncpus", Coolio_Utils_ncpus, 0);
34
+ rb_define_singleton_method(cCoolio_Utils, "maxfds", Coolio_Utils_maxfds, 0);
35
+ rb_define_singleton_method(cCoolio_Utils, "maxfds=", Coolio_Utils_setmaxfds, 1);
36
+ }
37
+
38
+ /**
39
+ * call-seq:
40
+ * Coolio::Utils.ncpus -> Integer
41
+ *
42
+ * Return the number of CPUs in the present system
43
+ */
44
+ static VALUE Coolio_Utils_ncpus(VALUE self)
45
+ {
46
+ int ncpus = 0;
47
+
48
+ #ifdef HAVE_LINUX_PROCFS
49
+ #define HAVE_COOLIO_UTILS_NCPUS
50
+ char buf[512];
51
+ FILE *cpuinfo;
52
+
53
+ if(!(cpuinfo = fopen("/proc/cpuinfo", "r")))
54
+ rb_sys_fail("fopen");
55
+
56
+ while(fgets(buf, 512, cpuinfo)) {
57
+ if(!strncmp(buf, "processor", 9))
58
+ ncpus++;
59
+ }
60
+ #endif
61
+
62
+ #ifdef HAVE_SYSCTLBYNAME
63
+ #define HAVE_COOLIO_UTILS_NCPUS
64
+ size_t size = sizeof(int);
65
+
66
+ if(sysctlbyname("hw.ncpu", &ncpus, &size, NULL, 0))
67
+ return INT2NUM(1);
68
+ #endif
69
+
70
+ #ifndef HAVE_COOLIO_UTILS_NCPUS
71
+ rb_raise(rb_eRuntimeError, "operation not supported");
72
+ #endif
73
+
74
+ return INT2NUM(ncpus);
75
+ }
76
+
77
+ /**
78
+ * call-seq:
79
+ * Coolio::Utils.maxfds -> Integer
80
+ *
81
+ * Return the maximum number of files descriptors available to the process
82
+ */
83
+ static VALUE Coolio_Utils_maxfds(VALUE self)
84
+ {
85
+ #ifdef HAVE_SYS_RESOURCE_H
86
+ struct rlimit rlim;
87
+
88
+ if(getrlimit(RLIMIT_NOFILE, &rlim) < 0)
89
+ rb_sys_fail("getrlimit");
90
+
91
+ return INT2NUM(rlim.rlim_cur);
92
+ #endif
93
+
94
+ #ifndef HAVE_SYS_RESOURCE_H
95
+ rb_raise(rb_eRuntimeError, "operation not supported");
96
+ #endif
97
+ }
98
+
99
+ /**
100
+ * call-seq:
101
+ * Coolio::Utils.maxfds=(count) -> Integer
102
+ *
103
+ * Set the number of file descriptors available to the process. May require
104
+ * superuser privileges.
105
+ */
106
+ static VALUE Coolio_Utils_setmaxfds(VALUE self, VALUE max)
107
+ {
108
+ #ifdef HAVE_SYS_RESOURCE_H
109
+ struct rlimit rlim;
110
+
111
+ rlim.rlim_cur = NUM2INT(max);
112
+
113
+ if(setrlimit(RLIMIT_NOFILE, &rlim) < 0)
114
+ rb_sys_fail("setrlimit");
115
+
116
+ return max;
117
+ #endif
118
+
119
+ #ifndef HAVE_SYS_RESOURCE_H
120
+ rb_raise(rb_eRuntimeError, "operation not supported");
121
+ #endif
122
+ }
@@ -0,0 +1,264 @@
1
+ /*
2
+ * Copyright (C) 2007-10 Tony Arcieri
3
+ * You may redistribute this under the terms of the Ruby license.
4
+ * See LICENSE for details
5
+ */
6
+
7
+ #include "ruby.h"
8
+ #include "ev_wrap.h"
9
+
10
+ #include "cool.io.h"
11
+
12
+ static VALUE mCoolio = Qnil;
13
+ static VALUE cCoolio_Watcher = Qnil;
14
+
15
+ static VALUE Coolio_Watcher_allocate(VALUE klass);
16
+ static void Coolio_Watcher_mark(struct Coolio_Watcher *watcher);
17
+ static void Coolio_Watcher_free(struct Coolio_Watcher *watcher);
18
+
19
+ static VALUE Coolio_Watcher_initialize(VALUE self);
20
+ static VALUE Coolio_Watcher_attach(VALUE self, VALUE loop);
21
+ static VALUE Coolio_Watcher_detach(VALUE self);
22
+ static VALUE Coolio_Watcher_enable(VALUE self);
23
+ static VALUE Coolio_Watcher_disable(VALUE self);
24
+ static VALUE Coolio_Watcher_evloop(VALUE self);
25
+ static VALUE Coolio_Watcher_attached(VALUE self);
26
+ static VALUE Coolio_Watcher_enabled(VALUE self);
27
+
28
+ /*
29
+ * Watchers are Coolio's event observers. They contain a set of callback
30
+ * methods prefixed by on_* which fire whenever events occur.
31
+ *
32
+ * In order for a watcher to fire events it must be attached to a running
33
+ * loop. Every watcher has an attach and detach method to control which
34
+ * loop it's associated with.
35
+ *
36
+ * Watchers also have an enable and disable method. This allows a watcher
37
+ * to temporarily ignore certain events while remaining attached to a given
38
+ * loop. This is good for watchers which need to be toggled on and off.
39
+ */
40
+ void Init_coolio_watcher()
41
+ {
42
+ mCoolio = rb_define_module("Coolio");
43
+ cCoolio_Watcher = rb_define_class_under(mCoolio, "Watcher", rb_cObject);
44
+ rb_define_alloc_func(cCoolio_Watcher, Coolio_Watcher_allocate);
45
+
46
+ rb_define_method(cCoolio_Watcher, "initialize", Coolio_Watcher_initialize, 0);
47
+ rb_define_method(cCoolio_Watcher, "attach", Coolio_Watcher_attach, 1);
48
+ rb_define_method(cCoolio_Watcher, "detach", Coolio_Watcher_detach, 0);
49
+ rb_define_method(cCoolio_Watcher, "enable", Coolio_Watcher_enable, 0);
50
+ rb_define_method(cCoolio_Watcher, "disable", Coolio_Watcher_disable, 0);
51
+ rb_define_method(cCoolio_Watcher, "evloop", Coolio_Watcher_evloop, 0);
52
+ rb_define_method(cCoolio_Watcher, "attached?", Coolio_Watcher_attached, 0);
53
+ rb_define_method(cCoolio_Watcher, "enabled?", Coolio_Watcher_enabled, 0);
54
+ }
55
+
56
+ static VALUE Coolio_Watcher_allocate(VALUE klass)
57
+ {
58
+ struct Coolio_Watcher *watcher_data = (struct Coolio_Watcher *)xmalloc(sizeof(struct Coolio_Watcher));
59
+
60
+ watcher_data->loop = Qnil;
61
+ watcher_data->enabled = 0;
62
+
63
+ return Data_Wrap_Struct(klass, Coolio_Watcher_mark, Coolio_Watcher_free, watcher_data);
64
+ }
65
+
66
+ static void Coolio_Watcher_mark(struct Coolio_Watcher *watcher_data)
67
+ {
68
+ if(watcher_data->loop != Qnil)
69
+ rb_gc_mark(watcher_data->loop);
70
+ }
71
+
72
+ static void Coolio_Watcher_free(struct Coolio_Watcher *watcher_data)
73
+ {
74
+ xfree(watcher_data);
75
+ }
76
+
77
+ static VALUE Coolio_Watcher_initialize(VALUE self)
78
+ {
79
+ rb_raise(rb_eRuntimeError, "watcher base class should not be initialized directly");
80
+ }
81
+
82
+ /**
83
+ * call-seq:
84
+ * Coolio::Watcher.attach(loop) -> Coolio::Watcher
85
+ *
86
+ * Attach the watcher to the given Coolio::Loop. If the watcher is already attached
87
+ * to a loop, detach it from the old one and attach it to the new one.
88
+ */
89
+ static VALUE Coolio_Watcher_attach(VALUE self, VALUE loop)
90
+ {
91
+ VALUE loop_watchers, active_watchers;
92
+ struct Coolio_Watcher *watcher_data;
93
+
94
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
95
+ watcher_data->enabled = 1;
96
+
97
+ loop_watchers = rb_iv_get(loop, "@watchers");
98
+
99
+ if(loop_watchers == Qnil) {
100
+ /* we should never get here */
101
+ loop_watchers = rb_hash_new();
102
+ rb_iv_set(loop, "@watchers", loop_watchers);
103
+ }
104
+
105
+ /* Add us to the loop's array of active watchers. This is mainly done
106
+ * to keep the VM from garbage collecting watchers that are associated
107
+ * with a loop (and also lets you see within Ruby which watchers are
108
+ * associated with a given loop), but isn't really necessary for any
109
+ * other reason */
110
+ rb_hash_aset(loop_watchers, self, Qtrue);
111
+
112
+ active_watchers = rb_iv_get(loop, "@active_watchers");
113
+ if(active_watchers == Qnil)
114
+ active_watchers = INT2NUM(1);
115
+ else
116
+ active_watchers = INT2NUM(NUM2INT(active_watchers) + 1);
117
+ rb_iv_set(loop, "@active_watchers", active_watchers);
118
+
119
+ return self;
120
+ }
121
+
122
+ /**
123
+ * call-seq:
124
+ * Coolio::Watcher.detach -> Coolio::Watcher
125
+ *
126
+ * Detach the watcher from its current Coolio::Loop.
127
+ */
128
+ static VALUE Coolio_Watcher_detach(VALUE self)
129
+ {
130
+ struct Coolio_Watcher *watcher_data;
131
+ struct Coolio_Loop *loop_data;
132
+ VALUE loop_watchers;
133
+ int i;
134
+
135
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
136
+
137
+ if(watcher_data->loop == Qnil)
138
+ rb_raise(rb_eRuntimeError, "not attached to a loop");
139
+
140
+ loop_watchers = rb_iv_get(watcher_data->loop, "@watchers");
141
+
142
+ /* Remove us from the loop's array of active watchers. This likely
143
+ * has negative performance and scalability characteristics as this
144
+ * isn't an O(1) operation. Hopefully there's a better way...
145
+ * Trying a hash for now... */
146
+ rb_hash_delete(loop_watchers, self);
147
+
148
+ if(watcher_data->enabled) {
149
+ rb_iv_set(
150
+ watcher_data->loop,
151
+ "@active_watchers",
152
+ INT2NUM(NUM2INT(rb_iv_get(watcher_data->loop, "@active_watchers")) - 1)
153
+ );
154
+ }
155
+
156
+ watcher_data->enabled = 0;
157
+
158
+ Data_Get_Struct(watcher_data->loop, struct Coolio_Loop, loop_data);
159
+
160
+ /* Iterate through the events in the loop's event buffer. If there
161
+ * are any pending events from this watcher, mark them NULL. The
162
+ * dispatch loop will skip them. This prevents watchers earlier
163
+ * in the event buffer from detaching others which may have pending
164
+ * events in the buffer but get garbage collected in the meantime */
165
+ for(i = 0; i < loop_data->events_received; i++) {
166
+ if(loop_data->eventbuf[i].watcher == self)
167
+ loop_data->eventbuf[i].watcher = Qnil;
168
+ }
169
+
170
+ watcher_data->loop = Qnil;
171
+
172
+ return self;
173
+ }
174
+
175
+ /**
176
+ * call-seq:
177
+ * Coolio::Watcher.enable -> Coolio::Watcher
178
+ *
179
+ * Re-enable a watcher which has been temporarily disabled. See the
180
+ * disable method for a more thorough explanation.
181
+ */
182
+ static VALUE Coolio_Watcher_enable(VALUE self)
183
+ {
184
+ struct Coolio_Watcher *watcher_data;
185
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
186
+
187
+ if(watcher_data->enabled)
188
+ rb_raise(rb_eRuntimeError, "already enabled");
189
+
190
+ watcher_data->enabled = 1;
191
+
192
+ rb_iv_set(
193
+ watcher_data->loop,
194
+ "@active_watchers",
195
+ INT2NUM(NUM2INT(rb_iv_get(watcher_data->loop, "@active_watchers")) + 1)
196
+ );
197
+
198
+ return self;
199
+ }
200
+
201
+ /**
202
+ * call-seq:
203
+ * Coolio::Watcher.disable -> Coolio::Watcher
204
+ *
205
+ * Temporarily disable an event watcher which is attached to a loop.
206
+ * This is useful if you wish to toggle event monitoring on and off.
207
+ */
208
+ static VALUE Coolio_Watcher_disable(VALUE self)
209
+ {
210
+ struct Coolio_Watcher *watcher_data;
211
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
212
+
213
+ if(!watcher_data->enabled)
214
+ rb_raise(rb_eRuntimeError, "already disabled");
215
+
216
+ watcher_data->enabled = 0;
217
+
218
+ rb_iv_set(
219
+ watcher_data->loop,
220
+ "@active_watchers",
221
+ INT2NUM(NUM2INT(rb_iv_get(watcher_data->loop, "@active_watchers")) - 1)
222
+ );
223
+
224
+ return self;
225
+ }
226
+
227
+ /**
228
+ * call-seq:
229
+ * Coolio::Watcher.evloop -> Coolio::Loop
230
+ *
231
+ * Return the loop to which we're currently attached
232
+ */
233
+ static VALUE Coolio_Watcher_evloop(VALUE self)
234
+ {
235
+ struct Coolio_Watcher *watcher_data;
236
+
237
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
238
+ return watcher_data->loop;
239
+ }
240
+
241
+ /**
242
+ * call-seq:
243
+ * Coolio::Watcher.attached? -> Boolean
244
+ *
245
+ * Is the watcher currently attached to an event loop?
246
+ */
247
+ static VALUE Coolio_Watcher_attached(VALUE self)
248
+ {
249
+ return Coolio_Watcher_evloop(self) != Qnil;
250
+ }
251
+
252
+ /**
253
+ * call-seq:
254
+ * Coolio::Watcher.enabled? -> Boolean
255
+ *
256
+ * Is the watcher currently enabled?
257
+ */
258
+ static VALUE Coolio_Watcher_enabled(VALUE self)
259
+ {
260
+ struct Coolio_Watcher *watcher_data;
261
+ Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
262
+
263
+ return watcher_data->enabled ? Qtrue : Qfalse;
264
+ }