cool.io 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +25 -0
- data/CHANGES +199 -0
- data/LICENSE +20 -0
- data/README.markdown +4 -0
- data/Rakefile +98 -0
- data/VERSION +1 -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 +69 -0
- data/ext/cool.io/iowatcher.c +189 -0
- data/ext/cool.io/libev.c +8 -0
- data/ext/cool.io/loop.c +303 -0
- data/ext/cool.io/stat_watcher.c +191 -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/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/libev/Changes +364 -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 +3867 -0
- data/ext/libev/ev.h +826 -0
- data/ext/libev/ev_epoll.c +234 -0
- data/ext/libev/ev_kqueue.c +198 -0
- data/ext/libev/ev_poll.c +148 -0
- data/ext/libev/ev_port.c +164 -0
- data/ext/libev/ev_select.c +307 -0
- data/ext/libev/ev_vars.h +197 -0
- data/ext/libev/ev_win32.c +153 -0
- data/ext/libev/ev_wrap.h +186 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/ext/libev/update_ev_wrap +19 -0
- data/lib/.gitignore +2 -0
- data/lib/cool.io.rb +30 -0
- data/lib/cool.io/async_watcher.rb +43 -0
- data/lib/cool.io/dns_resolver.rb +220 -0
- data/lib/cool.io/eventmachine.rb +234 -0
- data/lib/cool.io/http_client.rb +419 -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 +224 -0
- data/lib/cool.io/timer_watcher.rb +17 -0
- data/lib/coolio.rb +2 -0
- data/lib/rev.rb +4 -0
- data/spec/async_watcher_spec.rb +57 -0
- data/spec/possible_tests/schedules_other_threads.rb +48 -0
- data/spec/possible_tests/test_on_resolve_failed.rb +9 -0
- data/spec/possible_tests/test_resolves.rb +27 -0
- data/spec/possible_tests/test_write_during_resolve.rb +27 -0
- data/spec/possible_tests/works_straight.rb +71 -0
- data/spec/spec_helper.rb +5 -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 +184 -0
@@ -0,0 +1,191 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2009-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
|
+
#include "watcher.h"
|
12
|
+
|
13
|
+
static VALUE mCoolio = Qnil;
|
14
|
+
static VALUE cCoolio_Watcher = Qnil;
|
15
|
+
static VALUE cCoolio_StatWatcher = Qnil;
|
16
|
+
static VALUE cCoolio_Loop = Qnil;
|
17
|
+
|
18
|
+
static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self);
|
19
|
+
static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop);
|
20
|
+
static VALUE Coolio_StatWatcher_detach(VALUE self);
|
21
|
+
static VALUE Coolio_StatWatcher_enable(VALUE self);
|
22
|
+
static VALUE Coolio_StatWatcher_disable(VALUE self);
|
23
|
+
static VALUE Coolio_StatWatcher_on_change(VALUE self);
|
24
|
+
static VALUE Coolio_StatWatcher_path(VALUE self);
|
25
|
+
|
26
|
+
static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_stat *stat, int revents);
|
27
|
+
static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents);
|
28
|
+
|
29
|
+
/*
|
30
|
+
* Coolio::StatWatcher lets you create either one-shot or periodic stats 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_stat_watcher()
|
35
|
+
{
|
36
|
+
mCoolio = rb_define_module("Coolio");
|
37
|
+
cCoolio_Watcher = rb_define_class_under(mCoolio, "Watcher", rb_cObject);
|
38
|
+
cCoolio_StatWatcher = rb_define_class_under(mCoolio, "StatWatcher", cCoolio_Watcher);
|
39
|
+
cCoolio_Loop = rb_define_class_under(mCoolio, "Loop", rb_cObject);
|
40
|
+
|
41
|
+
rb_define_method(cCoolio_StatWatcher, "initialize", Coolio_StatWatcher_initialize, -1);
|
42
|
+
rb_define_method(cCoolio_StatWatcher, "attach", Coolio_StatWatcher_attach, 1);
|
43
|
+
rb_define_method(cCoolio_StatWatcher, "detach", Coolio_StatWatcher_detach, 0);
|
44
|
+
rb_define_method(cCoolio_StatWatcher, "enable", Coolio_StatWatcher_enable, 0);
|
45
|
+
rb_define_method(cCoolio_StatWatcher, "disable", Coolio_StatWatcher_disable, 0);
|
46
|
+
rb_define_method(cCoolio_StatWatcher, "on_change", Coolio_StatWatcher_on_change, 0);
|
47
|
+
rb_define_method(cCoolio_StatWatcher, "path", Coolio_StatWatcher_path, 0);
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* call-seq:
|
52
|
+
* Coolio::StatWatcher.initialize(path, interval = 0) -> Coolio::StatWatcher
|
53
|
+
*
|
54
|
+
* Create a new Coolio::StatWatcher for the given path. This will monitor the
|
55
|
+
* given path for changes at the filesystem level. The interval argument
|
56
|
+
* specified how often in seconds the path should be polled for changes.
|
57
|
+
* Setting interval to zero uses an "automatic" value (typically around 5
|
58
|
+
* seconds) which optimizes performance. Otherwise, values less than
|
59
|
+
* 0.1 are not particularly meaningful. Where available (at present, on Linux)
|
60
|
+
* high performance file monitoring interfaces will be used instead of polling.
|
61
|
+
*/
|
62
|
+
static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
|
63
|
+
{
|
64
|
+
VALUE path, interval;
|
65
|
+
struct Coolio_Watcher *watcher_data;
|
66
|
+
|
67
|
+
rb_scan_args(argc, argv, "11", &path, &interval);
|
68
|
+
if(interval != Qnil)
|
69
|
+
interval = rb_convert_type(interval, T_FLOAT, "Float", "to_f");
|
70
|
+
|
71
|
+
path = rb_String(path);
|
72
|
+
rb_iv_set(self, "@path", path);
|
73
|
+
|
74
|
+
Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
|
75
|
+
|
76
|
+
watcher_data->dispatch_callback = Coolio_StatWatcher_dispatch_callback;
|
77
|
+
ev_stat_init(
|
78
|
+
&watcher_data->event_types.ev_stat,
|
79
|
+
Coolio_StatWatcher_libev_callback,
|
80
|
+
RSTRING_PTR(path),
|
81
|
+
interval == Qnil ? 0 : NUM2DBL(interval)
|
82
|
+
);
|
83
|
+
watcher_data->event_types.ev_stat.data = (void *)self;
|
84
|
+
|
85
|
+
return Qnil;
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* call-seq:
|
90
|
+
* Coolio::StatWatcher.attach(loop) -> Coolio::StatWatcher
|
91
|
+
*
|
92
|
+
* Attach the stat watcher to the given Coolio::Loop. If the watcher is already
|
93
|
+
* attached to a loop, detach it from the old one and attach it to the new one.
|
94
|
+
*/
|
95
|
+
static VALUE Coolio_StatWatcher_attach(VALUE self, VALUE loop)
|
96
|
+
{
|
97
|
+
ev_tstamp interval, timeout;
|
98
|
+
struct Coolio_Loop *loop_data;
|
99
|
+
struct Coolio_Watcher *watcher_data;
|
100
|
+
|
101
|
+
if(!rb_obj_is_kind_of(loop, cCoolio_Loop))
|
102
|
+
rb_raise(rb_eArgError, "expected loop to be an instance of Coolio::Loop");
|
103
|
+
|
104
|
+
Data_Get_Struct(loop, struct Coolio_Loop, loop_data);
|
105
|
+
Data_Get_Struct(self, struct Coolio_Watcher, watcher_data);
|
106
|
+
|
107
|
+
if(watcher_data->loop != Qnil)
|
108
|
+
Coolio_StatWatcher_detach(self);
|
109
|
+
|
110
|
+
watcher_data->loop = loop;
|
111
|
+
|
112
|
+
ev_stat_start(loop_data->ev_loop, &watcher_data->event_types.ev_stat);
|
113
|
+
rb_call_super(1, &loop);
|
114
|
+
|
115
|
+
return self;
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* call-seq:
|
120
|
+
* Coolio::StatWatcher.detach -> Coolio::StatWatcher
|
121
|
+
*
|
122
|
+
* Detach the stat watcher from its current Coolio::Loop.
|
123
|
+
*/
|
124
|
+
static VALUE Coolio_StatWatcher_detach(VALUE self)
|
125
|
+
{
|
126
|
+
Watcher_Detach(stat, self);
|
127
|
+
|
128
|
+
return self;
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* call-seq:
|
133
|
+
* Coolio::StatWatcher.enable -> Coolio::StatWatcher
|
134
|
+
*
|
135
|
+
* Re-enable a stat watcher which has been temporarily disabled. See the
|
136
|
+
* disable method for a more thorough explanation.
|
137
|
+
*/
|
138
|
+
static VALUE Coolio_StatWatcher_enable(VALUE self)
|
139
|
+
{
|
140
|
+
Watcher_Enable(stat, self);
|
141
|
+
|
142
|
+
return self;
|
143
|
+
}
|
144
|
+
|
145
|
+
/**
|
146
|
+
* call-seq:
|
147
|
+
* Coolio::StatWatcher.disable -> Coolio::StatWatcher
|
148
|
+
*
|
149
|
+
* Temporarily disable a stat watcher which is attached to a loop.
|
150
|
+
* This is useful if you wish to toggle event monitoring on and off.
|
151
|
+
*/
|
152
|
+
static VALUE Coolio_StatWatcher_disable(VALUE self)
|
153
|
+
{
|
154
|
+
Watcher_Disable(stat, self);
|
155
|
+
|
156
|
+
return self;
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* call-seq:
|
161
|
+
* Coolio::StatWatcher#on_change -> nil
|
162
|
+
*
|
163
|
+
* Called whenever the status of the given path changes
|
164
|
+
*/
|
165
|
+
static VALUE Coolio_StatWatcher_on_change(VALUE self)
|
166
|
+
{
|
167
|
+
return Qnil;
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* call-seq:
|
172
|
+
* Coolio::StatWatcher#path -> String
|
173
|
+
*
|
174
|
+
* Retrieve the path associated with this StatWatcher
|
175
|
+
*/
|
176
|
+
static VALUE Coolio_StatWatcher_path(VALUE self)
|
177
|
+
{
|
178
|
+
return rb_iv_get(self, "@path");
|
179
|
+
}
|
180
|
+
|
181
|
+
/* libev callback */
|
182
|
+
static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_stat *stat, int revents)
|
183
|
+
{
|
184
|
+
Coolio_Loop_process_event((VALUE)stat->data, revents);
|
185
|
+
}
|
186
|
+
|
187
|
+
/* Coolio::Loop dispatch callback */
|
188
|
+
static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents)
|
189
|
+
{
|
190
|
+
rb_funcall(self, rb_intern("on_change"), 0, 0);
|
191
|
+
}
|
@@ -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
|
+
}
|