evio 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/evio/ev.c ADDED
@@ -0,0 +1,108 @@
1
+ #include <ruby.h>
2
+ #include <ev.h>
3
+
4
+ #include "evio.h"
5
+
6
+
7
+ static void
8
+ prepare_cb(struct ev_loop *loop, ev_prepare *watcher, int revents)
9
+ {
10
+ prepare_data *data = watcher->data;
11
+
12
+ rb_funcall(data->block, rb_intern("call"), 0);
13
+ ev_prepare_stop(loop, watcher);
14
+ rb_gc_unregister_address(&data->block);
15
+ free(data);
16
+ free(watcher);
17
+ }
18
+
19
+ static void
20
+ timer_cb(struct ev_loop *loop, ev_timer *watcher, int revents)
21
+ {
22
+ timer_data *data = watcher->data;
23
+ VALUE rv;
24
+
25
+ rv = rb_funcall(data->block, rb_intern("call"), 0);
26
+
27
+ if (data->repeat == 0 || rv == Qfalse) {
28
+ // remove watcher from loop
29
+ ev_timer_stop(loop, watcher);
30
+ // make the block available for gc collect
31
+ rb_gc_unregister_address(&data->block);
32
+ // free resources unmanaged by the gc
33
+ free(data);
34
+ free(watcher);
35
+ }
36
+ }
37
+
38
+ static VALUE
39
+ set_timer(VALUE self, VALUE delay, VALUE repeat_delay)
40
+ {
41
+ ev_timer *watcher;
42
+ timer_data *data;
43
+ int type;
44
+ double dl, repeat_dl;
45
+
46
+ rb_secure(2);
47
+
48
+ if ((type = TYPE(delay)) == T_FLOAT || type == T_FIXNUM)
49
+ dl = NUM2DBL(delay);
50
+ else
51
+ rb_raise(rb_eArgError, "first argument must be a number");
52
+
53
+ if ((type = TYPE(repeat_delay)) == T_FLOAT || type == T_FIXNUM)
54
+ repeat_dl = NUM2DBL(repeat_delay);
55
+ else
56
+ rb_raise(rb_eArgError, "second argument must be a number");
57
+
58
+ if (!rb_block_given_p())
59
+ rb_raise(rb_eArgError, "a block is required");
60
+
61
+ watcher = ALLOC(ev_timer);
62
+ data = ALLOC(timer_data);
63
+ // bind the block to its outer scope and store for later use
64
+ data->block = rb_block_proc();
65
+ // don't let the gc collect it
66
+ rb_gc_register_address(&data->block);
67
+ watcher->data = data;
68
+ if (repeat_dl > 0) data->repeat = 1;
69
+ else data->repeat = 0;
70
+ ev_timer_init(watcher, timer_cb, dl, repeat_dl);
71
+ ev_timer_start(loop, watcher);
72
+
73
+ return Qnil;
74
+ }
75
+
76
+ static VALUE
77
+ start_loop(VALUE self)
78
+ {
79
+ ev_prepare *watcher;
80
+ prepare_data *data;
81
+
82
+ if (rb_block_given_p()) {
83
+ watcher = ALLOC(ev_prepare);
84
+ data = ALLOC(prepare_data);
85
+ data->block = rb_block_proc();
86
+ rb_gc_register_address(&data->block);
87
+ watcher->data = data;
88
+ ev_prepare_init(watcher, prepare_cb);
89
+ ev_prepare_start(loop, watcher);
90
+ }
91
+
92
+ ev_run(loop, 0);
93
+ return Qnil;
94
+ }
95
+
96
+ static VALUE
97
+ stop_loop(VALUE self)
98
+ {
99
+ ev_break(loop, EVBREAK_ALL);
100
+ return Qnil;
101
+ }
102
+
103
+ void init_ev(VALUE module)
104
+ {
105
+ rb_define_module_function(module, "set_timer", set_timer, 2);
106
+ rb_define_module_function(module, "start_loop", start_loop, 0);
107
+ rb_define_module_function(module, "stop_loop", stop_loop, 0);
108
+ }
data/ext/evio/evio.c ADDED
@@ -0,0 +1,14 @@
1
+ #include <ruby.h>
2
+ #include <ev.h>
3
+
4
+ #include "evio.h"
5
+
6
+
7
+ void Init_evio()
8
+ {
9
+ loop = EV_DEFAULT;
10
+ VALUE module = rb_define_module("Evio");
11
+ init_ev(module);
12
+ init_signal(module);
13
+ init_io(module);
14
+ }
data/ext/evio/evio.h ADDED
@@ -0,0 +1,33 @@
1
+
2
+ typedef struct {
3
+ int fd;
4
+ int closed;
5
+ enum {
6
+ file,
7
+ socket
8
+ } stream_type;
9
+
10
+ } io_stream;
11
+
12
+ struct block_wrapper {
13
+ VALUE block;
14
+ };
15
+
16
+ typedef struct block_wrapper signal_data;
17
+ typedef struct block_wrapper prepare_data;
18
+ typedef struct {
19
+ VALUE block;
20
+ int buffer_size;
21
+ char *buffer;
22
+ } io_read_data;
23
+ typedef struct {
24
+ VALUE block;
25
+ int repeat;
26
+ } timer_data;
27
+
28
+ struct ev_loop *loop;
29
+
30
+ void Init_evio();
31
+ void init_ev(VALUE module);
32
+ void init_signal(VALUE module);
33
+ void init_io(VALUE module);
@@ -0,0 +1,29 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ require 'mkmf'
4
+
5
+ HEADER_DIRS = [
6
+ '/opt/local/include',
7
+ '/usr/local/include',
8
+ Config::CONFIG['includedir'],
9
+ '/usr/include',
10
+ ]
11
+
12
+ LIB_DIRS = [
13
+ '/opt/local/lib',
14
+ '/usr/local/lib',
15
+ Config::CONFIG['libdir'],
16
+ '/usr/lib',
17
+ ]
18
+
19
+ dir_config('ev', HEADER_DIRS, LIB_DIRS)
20
+
21
+ unless find_header('ev.h')
22
+ abort 'cannot find libev headers, install it before continuing'
23
+ end
24
+
25
+ unless find_library('ev', 'ev_run')
26
+ abort 'cannot find libev'
27
+ end
28
+
29
+ create_makefile('evio/evio')
data/ext/evio/io.c ADDED
@@ -0,0 +1,170 @@
1
+ #include <errno.h>
2
+ #include <string.h>
3
+
4
+ #include <sys/types.h>
5
+ #include <sys/stat.h>
6
+ #include <fcntl.h>
7
+ #include <unistd.h>
8
+
9
+ #include <ruby.h>
10
+ #include <ev.h>
11
+
12
+ #include "evio.h"
13
+
14
+
15
+ VALUE cIO;
16
+
17
+ static void
18
+ io_free(io_stream *stream)
19
+ {
20
+ close(stream->fd);
21
+ free(stream);
22
+ }
23
+
24
+ static VALUE
25
+ io_open(int argc, VALUE *argv)
26
+ {
27
+ io_stream *stream;
28
+ char *path, *mode;
29
+ int flags, filemode;
30
+
31
+ rb_secure(2);
32
+
33
+ if (argc < 1 || argc > 3)
34
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", argc);
35
+
36
+ if (TYPE(argv[0]) != T_STRING)
37
+ rb_raise(rb_eArgError, "first argument must be a string");
38
+
39
+ path = RSTRING_PTR(rb_str_encode_ospath(argv[0]));
40
+
41
+ if (argc > 1) {
42
+ flags = -1;
43
+ if (TYPE(argv[1]) != T_STRING)
44
+ rb_raise(rb_eArgError, "second argument must be a string");
45
+ mode = RSTRING_PTR(argv[1]);
46
+ if (mode[0] == 'r') {
47
+ if (mode[1] == '\0')
48
+ flags = O_RDONLY;
49
+ else if (mode[1] == '+' && mode[2] == '\0')
50
+ flags = O_RDWR;
51
+ } else if (mode[0] == 'w') {
52
+ if (mode[1] == '\0')
53
+ flags = O_WRONLY | O_CREAT;
54
+ else if (mode[1] == '+' && mode[2] == '\0')
55
+ flags = O_RDWR | O_CREAT;
56
+ } else if (mode[0] == 'a') {
57
+ if (mode[1] == '\0')
58
+ flags = O_WRONLY | O_CREAT | O_APPEND;
59
+ else if (mode[1] == '+' && mode[2] == '\0')
60
+ flags = O_RDWR | O_CREAT | O_APPEND;
61
+ }
62
+ if (flags == -1) rb_raise(rb_eArgError, "invalid file mode string");
63
+ } else {
64
+ flags = O_RDONLY;
65
+ }
66
+
67
+ if (argc == 3) {
68
+ if (TYPE(argv[2]) != T_FIXNUM)
69
+ rb_raise(rb_eArgError, "third argument must be an integer");
70
+ filemode = FIX2INT(argv[2]);
71
+ } else {
72
+ filemode = 0644;
73
+ }
74
+
75
+ flags |= O_NONBLOCK;
76
+ stream = ALLOC(io_stream);
77
+ stream->fd = open(path, flags, filemode);
78
+
79
+ if (stream->fd == -1)
80
+ rb_raise(rb_eSystemCallError, "%s", strerror(errno));
81
+
82
+ return Data_Wrap_Struct(cIO, 0, io_free, stream);
83
+ }
84
+
85
+ static void
86
+ io_read_cb(struct ev_loop *loop, ev_io *watcher, int revents)
87
+ {
88
+ ssize_t read_count;
89
+ VALUE rv = Qnil;
90
+ VALUE ex = Qnil;
91
+ io_read_data *data = watcher->data;
92
+
93
+ read_count = read(watcher->fd, data->buffer, data->buffer_size);
94
+
95
+ if (read_count == -1) {
96
+ if (errno == EAGAIN) return;
97
+ else ex = rb_exc_new2(rb_eSystemCallError, strerror(errno));
98
+ }
99
+
100
+ if (read_count != 0) // not EOF
101
+ rv = rb_funcall(data->block, rb_intern("call"), 2, ex,
102
+ rb_str_new(data->buffer, read_count));
103
+
104
+ if (read_count == 0 || rv == Qfalse) {
105
+ ev_io_stop(loop, watcher);
106
+ rb_gc_unregister_address(&data->block);
107
+ free(data->buffer);
108
+ free(data);
109
+ free(watcher);
110
+ }
111
+ }
112
+
113
+ static VALUE
114
+ io_read(int argc, VALUE *argv, VALUE self)
115
+ {
116
+ ev_io *watcher;
117
+ io_read_data *data;
118
+ io_stream *stream;
119
+ int buffer_size;
120
+
121
+ rb_secure(2);
122
+
123
+ if (argc > 1)
124
+ rb_raise(rb_eArgError, "must provide zero or one arguments");
125
+
126
+ if (!rb_block_given_p())
127
+ rb_raise(rb_eArgError, "a block is required");
128
+
129
+ if (argc == 1) {
130
+ if (TYPE(argv[0]) != T_FIXNUM)
131
+ rb_raise(rb_eArgError, "first argument must be an integer");
132
+ buffer_size = FIX2INT(argv[0]);
133
+ } else {
134
+ buffer_size = 4096;
135
+ }
136
+
137
+ Data_Get_Struct(self, io_stream, stream);
138
+ watcher = ALLOC(ev_io);
139
+ data = ALLOC(io_read_data);
140
+ data->block = rb_block_proc();
141
+ data->buffer_size = buffer_size;
142
+ data->buffer = ALLOC_N(char, buffer_size);
143
+ rb_gc_register_address(&data->block);
144
+ watcher->data = data;
145
+ ev_io_init(watcher, io_read_cb, stream->fd, EV_READ);
146
+ ev_io_start(loop, watcher);
147
+
148
+ return Qnil;
149
+ }
150
+
151
+ static VALUE
152
+ io_close(VALUE self)
153
+ {
154
+ io_stream *stream;
155
+
156
+ Data_Get_Struct(self, io_stream, stream);
157
+ close(stream->fd);
158
+
159
+ return Qnil;
160
+ }
161
+
162
+ void init_io(VALUE module)
163
+ {
164
+ cIO = rb_define_class_under(module, "IO", rb_cObject);
165
+
166
+ rb_define_singleton_method(cIO, "open", io_open, -1);
167
+
168
+ rb_define_method(cIO, "read", io_read, -1);
169
+ rb_define_method(cIO, "close", io_close, 0);
170
+ }
data/ext/evio/signal.c ADDED
@@ -0,0 +1,308 @@
1
+ #include <ruby.h>
2
+ #include <ev.h>
3
+
4
+ #include "evio.h"
5
+
6
+ // mostly copied from signal.c(ruby source)
7
+
8
+ static const struct signals {
9
+ const char *signm;
10
+ int signo;
11
+ } siglist [] = {
12
+ {"EXIT", 0},
13
+ #ifdef SIGHUP
14
+ {"HUP", SIGHUP},
15
+ #endif
16
+ {"INT", SIGINT},
17
+ #ifdef SIGQUIT
18
+ {"QUIT", SIGQUIT},
19
+ #endif
20
+ #ifdef SIGILL
21
+ {"ILL", SIGILL},
22
+ #endif
23
+ #ifdef SIGTRAP
24
+ {"TRAP", SIGTRAP},
25
+ #endif
26
+ #ifdef SIGIOT
27
+ {"IOT", SIGIOT},
28
+ #endif
29
+ #ifdef SIGABRT
30
+ {"ABRT", SIGABRT},
31
+ #endif
32
+ #ifdef SIGEMT
33
+ {"EMT", SIGEMT},
34
+ #endif
35
+ #ifdef SIGFPE
36
+ {"FPE", SIGFPE},
37
+ #endif
38
+ #ifdef SIGKILL
39
+ {"KILL", SIGKILL},
40
+ #endif
41
+ #ifdef SIGBUS
42
+ {"BUS", SIGBUS},
43
+ #endif
44
+ #ifdef SIGSEGV
45
+ {"SEGV", SIGSEGV},
46
+ #endif
47
+ #ifdef SIGSYS
48
+ {"SYS", SIGSYS},
49
+ #endif
50
+ #ifdef SIGPIPE
51
+ {"PIPE", SIGPIPE},
52
+ #endif
53
+ #ifdef SIGALRM
54
+ {"ALRM", SIGALRM},
55
+ #endif
56
+ #ifdef SIGTERM
57
+ {"TERM", SIGTERM},
58
+ #endif
59
+ #ifdef SIGURG
60
+ {"URG", SIGURG},
61
+ #endif
62
+ #ifdef SIGSTOP
63
+ {"STOP", SIGSTOP},
64
+ #endif
65
+ #ifdef SIGTSTP
66
+ {"TSTP", SIGTSTP},
67
+ #endif
68
+ #ifdef SIGCONT
69
+ {"CONT", SIGCONT},
70
+ #endif
71
+ #ifdef SIGCHLD
72
+ {"CHLD", SIGCHLD},
73
+ #endif
74
+ #ifdef SIGCLD
75
+ {"CLD", SIGCLD},
76
+ #else
77
+ # ifdef SIGCHLD
78
+ {"CLD", SIGCHLD},
79
+ # endif
80
+ #endif
81
+ #ifdef SIGTTIN
82
+ {"TTIN", SIGTTIN},
83
+ #endif
84
+ #ifdef SIGTTOU
85
+ {"TTOU", SIGTTOU},
86
+ #endif
87
+ #ifdef SIGIO
88
+ {"IO", SIGIO},
89
+ #endif
90
+ #ifdef SIGXCPU
91
+ {"XCPU", SIGXCPU},
92
+ #endif
93
+ #ifdef SIGXFSZ
94
+ {"XFSZ", SIGXFSZ},
95
+ #endif
96
+ #ifdef SIGVTALRM
97
+ {"VTALRM", SIGVTALRM},
98
+ #endif
99
+ #ifdef SIGPROF
100
+ {"PROF", SIGPROF},
101
+ #endif
102
+ #ifdef SIGWINCH
103
+ {"WINCH", SIGWINCH},
104
+ #endif
105
+ #ifdef SIGUSR1
106
+ {"USR1", SIGUSR1},
107
+ #endif
108
+ #ifdef SIGUSR2
109
+ {"USR2", SIGUSR2},
110
+ #endif
111
+ #ifdef SIGLOST
112
+ {"LOST", SIGLOST},
113
+ #endif
114
+ #ifdef SIGMSG
115
+ {"MSG", SIGMSG},
116
+ #endif
117
+ #ifdef SIGPWR
118
+ {"PWR", SIGPWR},
119
+ #endif
120
+ #ifdef SIGPOLL
121
+ {"POLL", SIGPOLL},
122
+ #endif
123
+ #ifdef SIGDANGER
124
+ {"DANGER", SIGDANGER},
125
+ #endif
126
+ #ifdef SIGMIGRATE
127
+ {"MIGRATE", SIGMIGRATE},
128
+ #endif
129
+ #ifdef SIGPRE
130
+ {"PRE", SIGPRE},
131
+ #endif
132
+ #ifdef SIGGRANT
133
+ {"GRANT", SIGGRANT},
134
+ #endif
135
+ #ifdef SIGRETRACT
136
+ {"RETRACT", SIGRETRACT},
137
+ #endif
138
+ #ifdef SIGSOUND
139
+ {"SOUND", SIGSOUND},
140
+ #endif
141
+ #ifdef SIGINFO
142
+ {"INFO", SIGINFO},
143
+ #endif
144
+ {NULL, 0}
145
+ };
146
+
147
+ static int
148
+ signm2signo(const char *nm)
149
+ {
150
+ const struct signals *sigs;
151
+
152
+ for (sigs = siglist; sigs->signm; sigs++)
153
+ if (strcmp(sigs->signm, nm) == 0)
154
+ return sigs->signo;
155
+ return 0;
156
+ }
157
+
158
+ static const char*
159
+ signo2signm(int no)
160
+ {
161
+ const struct signals *sigs;
162
+
163
+ for (sigs = siglist; sigs->signm; sigs++)
164
+ if (sigs->signo == no)
165
+ return sigs->signm;
166
+ return 0;
167
+ }
168
+
169
+ static int
170
+ trap_signm(VALUE vsig)
171
+ {
172
+ int sig = -1;
173
+ const char *s;
174
+
175
+ switch (TYPE(vsig)) {
176
+ case T_FIXNUM:
177
+ sig = FIX2INT(vsig);
178
+ if (sig < 0 || sig >= NSIG) {
179
+ rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
180
+ }
181
+ break;
182
+
183
+ case T_SYMBOL:
184
+ s = rb_id2name(SYM2ID(vsig));
185
+ if (!s) rb_raise(rb_eArgError, "bad signal");
186
+ goto str_signal;
187
+
188
+ default:
189
+ s = StringValuePtr(vsig);
190
+
191
+ str_signal:
192
+ if (strncmp("SIG", s, 3) == 0)
193
+ s += 3;
194
+ sig = signm2signo(s);
195
+ if (sig == 0 && strcmp(s, "EXIT") != 0)
196
+ rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
197
+ }
198
+ return sig;
199
+ }
200
+
201
+ // TODO do something here
202
+ static void
203
+ default_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
204
+ {
205
+
206
+ }
207
+
208
+ static void
209
+ ignore_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
210
+ {
211
+
212
+ }
213
+
214
+ static void
215
+ exit_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
216
+ {
217
+ exit(watcher->signum);
218
+ }
219
+
220
+ static void
221
+ block_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
222
+ {
223
+ signal_data *data = watcher->data;
224
+ VALUE rv;
225
+
226
+ rv = rb_funcall(data->block, rb_intern("call"), 1, INT2FIX(watcher->signum));
227
+
228
+ if (rv == Qfalse) {
229
+ ev_signal_stop(loop, watcher);
230
+ rb_gc_unregister_address(&data->block);
231
+ free(data);
232
+ free(watcher);
233
+ }
234
+ }
235
+
236
+ static VALUE
237
+ sig_trap(int argc, VALUE *argv)
238
+ {
239
+ ev_signal *watcher;
240
+ VALUE cmd;
241
+ signal_data *data;
242
+ int sign;
243
+
244
+ rb_secure(2);
245
+
246
+ if (argc < 1 || argc > 2)
247
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
248
+
249
+ sign = trap_signm(argv[0]);
250
+ watcher = ALLOC(ev_signal);
251
+
252
+ if (argc == 1) {
253
+ data = ALLOC(signal_data);
254
+ data->block = rb_block_proc();
255
+ watcher->data = data;
256
+ rb_gc_register_address(&data->block);
257
+ ev_signal_init(watcher, block_cb, sign);
258
+ } else {
259
+ cmd = argv[1];
260
+ if (OBJ_TAINTED(cmd))
261
+ rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
262
+ if (!NIL_P(cmd)) {
263
+ switch (RSTRING_LEN(cmd)) {
264
+ case 0:
265
+ goto sig_ign;
266
+ break;
267
+ case 14:
268
+ if (strncmp(RSTRING_PTR(cmd), "SYSTEM_DEFAULT", 14) == 0) {
269
+ sig_dfl:
270
+ ev_signal_init(watcher, default_cb, sign);
271
+ }
272
+ break;
273
+ case 7:
274
+ if (strncmp(RSTRING_PTR(cmd), "SIG_IGN", 7) == 0) {
275
+ sig_ign:
276
+ ev_signal_init(watcher, ignore_cb, sign);
277
+ }
278
+ else if (strncmp(RSTRING_PTR(cmd), "SIG_DFL", 7) == 0) {
279
+ goto sig_dfl;
280
+ }
281
+ else if (strncmp(RSTRING_PTR(cmd), "DEFAULT", 7) == 0) {
282
+ goto sig_dfl;
283
+ }
284
+ break;
285
+ case 6:
286
+ if (strncmp(RSTRING_PTR(cmd), "IGNORE", 6) == 0)
287
+ goto sig_ign;
288
+ break;
289
+ case 4:
290
+ if (strncmp(RSTRING_PTR(cmd), "EXIT", 4) == 0) {
291
+ ev_signal_init(watcher, exit_cb, sign);
292
+ }
293
+ break;
294
+ }
295
+ }
296
+ }
297
+
298
+ ev_signal_start(loop, watcher);
299
+ return Qnil;
300
+ }
301
+
302
+ void
303
+ init_signal(VALUE module)
304
+ {
305
+ VALUE signal_module = rb_define_module_under(module, "Signal");
306
+
307
+ rb_define_module_function(signal_module, "trap", sig_trap, -1);
308
+ }
data/lib/evio.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'evio/signal'
2
+ require 'evio/evio'
@@ -0,0 +1,18 @@
1
+
2
+ module Evio
3
+
4
+ module Signal
5
+
6
+ def clear_signal_traps
7
+ # Remove all default handlers since they cause segfault
8
+ # with libev handlers
9
+ Signal.list.values.each do |s|
10
+ Signal.trap s, 'IGNORE'
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evio
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Thiago de Arruda
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description:
31
+ email: tpadilha84@gmail.com
32
+ executables: []
33
+ extensions:
34
+ - ext/evio/extconf.rb
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/evio/signal.rb
38
+ - lib/evio.rb
39
+ - ext/evio/ev.c
40
+ - ext/evio/evio.c
41
+ - ext/evio/io.c
42
+ - ext/evio/signal.c
43
+ - ext/evio/evio.h
44
+ - ext/evio/extconf.rb
45
+ homepage: http://rubygems.org/gems/evio
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.23
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Simple non-blocking IO
69
+ test_files: []