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.
Files changed (73) hide show
  1. data/.gitignore +25 -0
  2. data/CHANGES +199 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +4 -0
  5. data/Rakefile +98 -0
  6. data/VERSION +1 -0
  7. data/examples/echo_client.rb +38 -0
  8. data/examples/echo_server.rb +27 -0
  9. data/examples/google.rb +9 -0
  10. data/examples/httpclient.rb +38 -0
  11. data/ext/cool.io/.gitignore +5 -0
  12. data/ext/cool.io/cool.io.h +58 -0
  13. data/ext/cool.io/cool.io_ext.c +25 -0
  14. data/ext/cool.io/ev_wrap.h +8 -0
  15. data/ext/cool.io/extconf.rb +69 -0
  16. data/ext/cool.io/iowatcher.c +189 -0
  17. data/ext/cool.io/libev.c +8 -0
  18. data/ext/cool.io/loop.c +303 -0
  19. data/ext/cool.io/stat_watcher.c +191 -0
  20. data/ext/cool.io/timer_watcher.c +219 -0
  21. data/ext/cool.io/utils.c +122 -0
  22. data/ext/cool.io/watcher.c +264 -0
  23. data/ext/cool.io/watcher.h +71 -0
  24. data/ext/http11_client/.gitignore +5 -0
  25. data/ext/http11_client/ext_help.h +14 -0
  26. data/ext/http11_client/extconf.rb +6 -0
  27. data/ext/http11_client/http11_client.c +300 -0
  28. data/ext/http11_client/http11_parser.c +403 -0
  29. data/ext/http11_client/http11_parser.h +48 -0
  30. data/ext/http11_client/http11_parser.rl +173 -0
  31. data/ext/libev/Changes +364 -0
  32. data/ext/libev/LICENSE +36 -0
  33. data/ext/libev/README +58 -0
  34. data/ext/libev/README.embed +3 -0
  35. data/ext/libev/ev.c +3867 -0
  36. data/ext/libev/ev.h +826 -0
  37. data/ext/libev/ev_epoll.c +234 -0
  38. data/ext/libev/ev_kqueue.c +198 -0
  39. data/ext/libev/ev_poll.c +148 -0
  40. data/ext/libev/ev_port.c +164 -0
  41. data/ext/libev/ev_select.c +307 -0
  42. data/ext/libev/ev_vars.h +197 -0
  43. data/ext/libev/ev_win32.c +153 -0
  44. data/ext/libev/ev_wrap.h +186 -0
  45. data/ext/libev/test_libev_win32.c +123 -0
  46. data/ext/libev/update_ev_wrap +19 -0
  47. data/lib/.gitignore +2 -0
  48. data/lib/cool.io.rb +30 -0
  49. data/lib/cool.io/async_watcher.rb +43 -0
  50. data/lib/cool.io/dns_resolver.rb +220 -0
  51. data/lib/cool.io/eventmachine.rb +234 -0
  52. data/lib/cool.io/http_client.rb +419 -0
  53. data/lib/cool.io/io.rb +174 -0
  54. data/lib/cool.io/iowatcher.rb +17 -0
  55. data/lib/cool.io/listener.rb +93 -0
  56. data/lib/cool.io/loop.rb +130 -0
  57. data/lib/cool.io/meta.rb +49 -0
  58. data/lib/cool.io/server.rb +74 -0
  59. data/lib/cool.io/socket.rb +224 -0
  60. data/lib/cool.io/timer_watcher.rb +17 -0
  61. data/lib/coolio.rb +2 -0
  62. data/lib/rev.rb +4 -0
  63. data/spec/async_watcher_spec.rb +57 -0
  64. data/spec/possible_tests/schedules_other_threads.rb +48 -0
  65. data/spec/possible_tests/test_on_resolve_failed.rb +9 -0
  66. data/spec/possible_tests/test_resolves.rb +27 -0
  67. data/spec/possible_tests/test_write_during_resolve.rb +27 -0
  68. data/spec/possible_tests/works_straight.rb +71 -0
  69. data/spec/spec_helper.rb +5 -0
  70. data/spec/timer_watcher_spec.rb +55 -0
  71. data/spec/unix_listener_spec.rb +25 -0
  72. data/spec/unix_server_spec.rb +25 -0
  73. 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
+ }
@@ -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
+ }