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.
- data/.gitignore +26 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/CHANGES.md +177 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +172 -0
- data/Rakefile +81 -0
- data/cool.io.gemspec +28 -0
- data/examples/dslified_echo_client.rb +34 -0
- data/examples/dslified_echo_server.rb +24 -0
- data/examples/echo_client.rb +38 -0
- data/examples/echo_server.rb +27 -0
- data/examples/google.rb +9 -0
- data/examples/httpclient.rb +38 -0
- data/ext/cool.io/.gitignore +5 -0
- data/ext/cool.io/cool.io.h +58 -0
- data/ext/cool.io/cool.io_ext.c +25 -0
- data/ext/cool.io/ev_wrap.h +8 -0
- data/ext/cool.io/extconf.rb +73 -0
- data/ext/cool.io/iowatcher.c +189 -0
- data/ext/cool.io/libev.c +8 -0
- data/ext/cool.io/loop.c +301 -0
- data/ext/cool.io/stat_watcher.c +269 -0
- data/ext/cool.io/timer_watcher.c +219 -0
- data/ext/cool.io/utils.c +122 -0
- data/ext/cool.io/watcher.c +264 -0
- data/ext/cool.io/watcher.h +71 -0
- data/ext/http11_client/.gitignore +5 -0
- data/ext/http11_client/LICENSE +31 -0
- data/ext/http11_client/ext_help.h +14 -0
- data/ext/http11_client/extconf.rb +6 -0
- data/ext/http11_client/http11_client.c +300 -0
- data/ext/http11_client/http11_parser.c +403 -0
- data/ext/http11_client/http11_parser.h +48 -0
- data/ext/http11_client/http11_parser.rl +173 -0
- data/ext/iobuffer/extconf.rb +9 -0
- data/ext/iobuffer/iobuffer.c +765 -0
- data/ext/libev/Changes +388 -0
- data/ext/libev/LICENSE +36 -0
- data/ext/libev/README +58 -0
- data/ext/libev/README.embed +3 -0
- data/ext/libev/ev.c +4803 -0
- data/ext/libev/ev.h +845 -0
- data/ext/libev/ev_epoll.c +279 -0
- data/ext/libev/ev_kqueue.c +214 -0
- data/ext/libev/ev_poll.c +148 -0
- data/ext/libev/ev_port.c +185 -0
- data/ext/libev/ev_select.c +314 -0
- data/ext/libev/ev_vars.h +203 -0
- data/ext/libev/ev_win32.c +163 -0
- data/ext/libev/ev_wrap.h +200 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/lib/.gitignore +2 -0
- data/lib/cool.io.rb +32 -0
- data/lib/cool.io/async_watcher.rb +43 -0
- data/lib/cool.io/custom_require.rb +9 -0
- data/lib/cool.io/dns_resolver.rb +225 -0
- data/lib/cool.io/dsl.rb +135 -0
- data/lib/cool.io/eventmachine.rb +234 -0
- data/lib/cool.io/http_client.rb +427 -0
- data/lib/cool.io/io.rb +174 -0
- data/lib/cool.io/iowatcher.rb +17 -0
- data/lib/cool.io/listener.rb +93 -0
- data/lib/cool.io/loop.rb +130 -0
- data/lib/cool.io/meta.rb +49 -0
- data/lib/cool.io/server.rb +74 -0
- data/lib/cool.io/socket.rb +230 -0
- data/lib/cool.io/timer_watcher.rb +17 -0
- data/lib/cool.io/version.rb +5 -0
- data/lib/coolio.rb +2 -0
- data/spec/async_watcher_spec.rb +57 -0
- data/spec/dns_spec.rb +39 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/stat_watcher_spec.rb +77 -0
- data/spec/timer_watcher_spec.rb +55 -0
- data/spec/unix_listener_spec.rb +25 -0
- data/spec/unix_server_spec.rb +25 -0
- 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
|
+
}
|
data/ext/cool.io/utils.c
ADDED
@@ -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
|
+
}
|