io-epoll 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +22 -4
- data/examples/epoll_server.rb +1 -1
- data/ext/io/epoll/epoll.c +182 -43
- data/ext/io/epoll/extconf.rb +3 -2
- data/io-epoll.gemspec +3 -3
- data/lib/io/epoll.rb +7 -3
- data/test/test_epoll.rb +125 -39
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97d310cf1317528f3b0d1315862f1365a9a3480b
|
4
|
+
data.tar.gz: 87e9317da46fa65ad67f9f3dd66a0589ca44adf6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4c7b4cfbf7b113800d952650c8c49948e63ce0c4de8a80be3f2a90ebdfba0cb3b8a0672ed518e853550c13cf48907a31485731c70f494213ffb173c212d01c0
|
7
|
+
data.tar.gz: 4769b5237627dbff6621fae9bb9a8044d8560689f684b328ee50c51a90ab45a9a0a3dac1f234d0de73f66f80746141ccf55576085995121a2e35450b0718564d
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -32,8 +32,14 @@ epoll = Epoll.create
|
|
32
32
|
epoll.ctl(Epoll::CTL_ADD, io, Epoll::IN)
|
33
33
|
|
34
34
|
# and you can use short way
|
35
|
+
|
36
|
+
# IO object add to interest list
|
35
37
|
epoll.add(io, Epoll::IN) # same way to epoll.ctl(Epoll::CTL_ADD, io, Epoll::IN)
|
36
|
-
|
38
|
+
|
39
|
+
# change waiting events
|
40
|
+
epoll.mod(io, Epoll::OUT) # same way to epoll.ctl(Epoll::CTL_MOD, io, Epoll::OUT)
|
41
|
+
|
42
|
+
# remove from interest list
|
37
43
|
epoll.del(io) # same way to epoll.ctl(Epoll::CTL_DEL, io)
|
38
44
|
|
39
45
|
loop do
|
@@ -46,7 +52,7 @@ loop do
|
|
46
52
|
evlist = epoll.wait
|
47
53
|
|
48
54
|
# ev is instance of IO::Epoll::Event like `struct epoll_event`
|
49
|
-
# it's
|
55
|
+
# it's instance of `class IO::Epoll::Event < Struct.new(:data, :events); end`
|
50
56
|
evlist.each do |ev|
|
51
57
|
# IO::Epoll::Event#events is event flag bits (Fixnum)
|
52
58
|
if (ev.events & Epoll::IN) != 0
|
@@ -65,6 +71,12 @@ epoll.close #=> nil
|
|
65
71
|
|
66
72
|
# and you can check closed
|
67
73
|
epoll.closed? #=> true
|
74
|
+
|
75
|
+
# and very useful way is that call `create` (or `new`) with block like Ruby IO.open
|
76
|
+
# return: block result
|
77
|
+
Epoll.create do |epoll|
|
78
|
+
# ensure automatic call `epoll.close` when out block
|
79
|
+
end
|
68
80
|
```
|
69
81
|
|
70
82
|
## ctl options
|
@@ -84,7 +96,7 @@ event flags|ctl|wait|description
|
|
84
96
|
**IO::Epoll::HUP**|o|o|peer socket was shutdown
|
85
97
|
**IO::Epoll::OUT**|o|o|writable
|
86
98
|
**IO::Epoll::ET**|o|x|use edge trigger
|
87
|
-
**IO::Epoll
|
99
|
+
**IO::Epoll::ONESHOT**|o|x|auto watching stop when notified(but stay in list)
|
88
100
|
**IO::Epoll::ERR**|x|o|raise error
|
89
101
|
**IO::Epoll::HUP**|x|o|raise hang up
|
90
102
|
|
@@ -104,7 +116,13 @@ Or install it yourself as:
|
|
104
116
|
|
105
117
|
$ gem install io-epoll
|
106
118
|
|
107
|
-
#
|
119
|
+
# Pro Tips
|
120
|
+
|
121
|
+
- Support call without GVL in CRuby (use rb\_thread\_call\_without\_gvl())
|
122
|
+
- Close on exec flag set by default if you can use (use epoll_create1(EPOLL_CLOEXEC))
|
123
|
+
- IO::Epoll#wait max return array size is 256 on one time (of course, overflowing and then carried next)
|
124
|
+
|
125
|
+
# Fork Me !
|
108
126
|
|
109
127
|
This is experimental implementation.
|
110
128
|
I'm waiting for your idea and Pull Request !
|
data/examples/epoll_server.rb
CHANGED
data/ext/io/epoll/epoll.c
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include "ruby/io.h"
|
3
3
|
#include "ruby/thread.h"
|
4
|
+
|
5
|
+
#ifdef HAVE_SYS_EPOLL_H
|
6
|
+
|
4
7
|
#include <sys/epoll.h>
|
8
|
+
#include <fcntl.h>
|
9
|
+
|
10
|
+
#define EPOLL_WAIT_MAX_EVENTS 256
|
5
11
|
|
6
12
|
VALUE cIO_Epoll;
|
13
|
+
VALUE cIO_Epoll_Constants;
|
7
14
|
VALUE cIO_Epoll_Event;
|
8
15
|
|
9
16
|
struct Epoll {
|
@@ -11,10 +18,15 @@ struct Epoll {
|
|
11
18
|
int ev_len;
|
12
19
|
};
|
13
20
|
|
14
|
-
|
21
|
+
enum {
|
22
|
+
EPOLL_EVENT_DATA = 0,
|
23
|
+
EPOLL_EVENT_EVENTS = 1
|
24
|
+
};
|
25
|
+
|
26
|
+
inline static void
|
15
27
|
epoll_fd_close(int epfd)
|
16
28
|
{
|
17
|
-
|
29
|
+
close(epfd);
|
18
30
|
}
|
19
31
|
|
20
32
|
static void
|
@@ -79,6 +91,36 @@ rb_epoll_allocate(VALUE klass)
|
|
79
91
|
return TypedData_Make_Struct(klass, struct Epoll, &epoll_data_type, ptr);
|
80
92
|
}
|
81
93
|
|
94
|
+
static VALUE
|
95
|
+
rb_epoll_close(VALUE self)
|
96
|
+
{
|
97
|
+
struct Epoll *ptr = get_epoll(self);
|
98
|
+
epoll_check_closed(ptr);
|
99
|
+
epoll_fd_close(ptr->epfd);
|
100
|
+
ptr->epfd = -1;
|
101
|
+
return Qnil;
|
102
|
+
}
|
103
|
+
|
104
|
+
static VALUE
|
105
|
+
ensure_epoll_close(VALUE ep)
|
106
|
+
{
|
107
|
+
VALUE closed = rb_check_funcall(ep, rb_intern("closed?"), 0, 0);
|
108
|
+
if (closed != Qundef && RTEST(closed)) return ep;
|
109
|
+
rb_epoll_close(ep);
|
110
|
+
return ep;
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE
|
114
|
+
rb_epoll_s_new(VALUE klass)
|
115
|
+
{
|
116
|
+
VALUE ep = rb_class_new_instance(0, NULL, klass);
|
117
|
+
|
118
|
+
if (rb_block_given_p()) {
|
119
|
+
return rb_ensure(rb_yield, ep, ensure_epoll_close, ep);
|
120
|
+
}
|
121
|
+
return ep;
|
122
|
+
}
|
123
|
+
|
82
124
|
static VALUE
|
83
125
|
rb_epoll_initialize(VALUE self)
|
84
126
|
{
|
@@ -87,9 +129,15 @@ rb_epoll_initialize(VALUE self)
|
|
87
129
|
|
88
130
|
TypedData_Get_Struct(self, struct Epoll, &epoll_data_type, ptr);
|
89
131
|
if (ptr->epfd < 0) epoll_fd_close(ptr->epfd);
|
90
|
-
|
132
|
+
|
133
|
+
#if defined(HAVE_EPOLL_CREATE1) && defined(EPOLL_CLOEXEC)
|
134
|
+
epfd = epoll_create1(EPOLL_CLOEXEC);
|
135
|
+
#else
|
136
|
+
epfd = epoll_create(1024);
|
137
|
+
#endif
|
138
|
+
|
91
139
|
if (epfd == -1) {
|
92
|
-
rb_sys_fail("epoll_create was failed");
|
140
|
+
rb_sys_fail("epoll_create() was failed");
|
93
141
|
}
|
94
142
|
ptr->epfd = epfd;
|
95
143
|
ptr->ev_len = 0;
|
@@ -104,6 +152,42 @@ rb_epoll_initialize(VALUE self)
|
|
104
152
|
return self;
|
105
153
|
}
|
106
154
|
|
155
|
+
static VALUE
|
156
|
+
rb_epoll_initialize_copy(VALUE copy, VALUE orig)
|
157
|
+
{
|
158
|
+
struct Epoll *orig_ptr = get_epoll(orig);
|
159
|
+
struct Epoll *copy_ptr;
|
160
|
+
int epfd;
|
161
|
+
|
162
|
+
if (!OBJ_INIT_COPY(copy, orig)) return copy;
|
163
|
+
|
164
|
+
TypedData_Get_Struct(copy, struct Epoll, &epoll_data_type, copy_ptr);
|
165
|
+
epfd = dup(orig_ptr->epfd);
|
166
|
+
if (epfd == -1)
|
167
|
+
rb_sys_fail("dup() was failed");
|
168
|
+
copy_ptr->epfd = epfd;
|
169
|
+
copy_ptr->ev_len = orig_ptr->ev_len;
|
170
|
+
rb_ivar_set(copy, rb_intern("evlist"), rb_ivar_get(orig, rb_intern("evlist")));
|
171
|
+
return copy;
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE
|
175
|
+
rb_epoll_inspect(VALUE self)
|
176
|
+
{
|
177
|
+
struct Epoll *ptr = get_epoll(self);
|
178
|
+
VALUE result;
|
179
|
+
|
180
|
+
if (!ptr) return rb_any_to_s(self);
|
181
|
+
result = rb_str_new_cstr("#<");
|
182
|
+
rb_str_append(result, rb_class_name(CLASS_OF(self)));
|
183
|
+
rb_str_cat2(result, ":");
|
184
|
+
if (ptr->epfd < 0)
|
185
|
+
rb_str_cat(result, " (closed)", 9);
|
186
|
+
else
|
187
|
+
rb_str_catf(result, "fd %d", ptr->epfd);
|
188
|
+
return rb_str_cat2(result, ">");
|
189
|
+
}
|
190
|
+
|
107
191
|
static VALUE
|
108
192
|
rb_epoll_fileno(VALUE self)
|
109
193
|
{
|
@@ -115,9 +199,9 @@ rb_epoll_fileno(VALUE self)
|
|
115
199
|
inline static void
|
116
200
|
rb_epoll_evlist_add(VALUE self, VALUE io)
|
117
201
|
{
|
118
|
-
|
119
|
-
|
120
|
-
|
202
|
+
VALUE evlist = rb_ivar_get(self, rb_intern("evlist"));
|
203
|
+
rb_ary_push(evlist, io);
|
204
|
+
rb_ivar_set(self, rb_intern("evlist"), evlist);
|
121
205
|
}
|
122
206
|
|
123
207
|
inline static void
|
@@ -192,6 +276,7 @@ rb_epoll_ctl(int argc, VALUE *argv, VALUE self)
|
|
192
276
|
struct epoll_wait_args {
|
193
277
|
struct Epoll *ptr;
|
194
278
|
struct epoll_event *evlist;
|
279
|
+
int ev_len;
|
195
280
|
int timeout;
|
196
281
|
};
|
197
282
|
|
@@ -199,30 +284,37 @@ static void *
|
|
199
284
|
rb_epoll_wait_func(void *ptr)
|
200
285
|
{
|
201
286
|
const struct epoll_wait_args *data = ptr;
|
202
|
-
return (void*)(long)epoll_wait(data->ptr->epfd, data->evlist, data->
|
287
|
+
return (void*)(long)epoll_wait(data->ptr->epfd, data->evlist, data->ev_len, data->timeout);
|
203
288
|
}
|
204
289
|
|
205
290
|
static VALUE
|
206
291
|
rb_epoll_wait(int argc, VALUE *argv, VALUE self)
|
207
292
|
{
|
208
293
|
struct Epoll *ptr = get_epoll(self);
|
294
|
+
struct epoll_event evlist[EPOLL_WAIT_MAX_EVENTS];
|
295
|
+
struct epoll_wait_args data;
|
296
|
+
int i, ready, timeout;
|
209
297
|
VALUE ready_evlist;
|
210
298
|
VALUE event;
|
211
|
-
struct epoll_event *evlist;
|
212
|
-
int i, ready;
|
213
|
-
int timeout = -1;
|
214
|
-
struct epoll_wait_args data;
|
215
299
|
|
216
|
-
|
300
|
+
switch (argc) {
|
301
|
+
case 0:
|
302
|
+
timeout = -1;
|
303
|
+
break;
|
304
|
+
case 1:
|
217
305
|
timeout = FIX2INT(argv[0]);
|
306
|
+
break;
|
307
|
+
default:
|
308
|
+
rb_raise(rb_eArgError, "too many argument");
|
309
|
+
break;
|
310
|
+
}
|
218
311
|
|
219
312
|
if (ptr->ev_len <= 0)
|
220
313
|
rb_raise(rb_eIOError, "empty interest list");
|
221
314
|
|
222
|
-
evlist = ruby_xmalloc(ptr->ev_len * sizeof(struct epoll_event));
|
223
|
-
|
224
315
|
data.ptr = ptr;
|
225
316
|
data.evlist = evlist;
|
317
|
+
data.ev_len = EPOLL_WAIT_MAX_EVENTS < ptr->ev_len ? EPOLL_WAIT_MAX_EVENTS : ptr->ev_len;
|
226
318
|
data.timeout = timeout;
|
227
319
|
|
228
320
|
RETRY:
|
@@ -232,7 +324,6 @@ RETRY:
|
|
232
324
|
goto RETRY;
|
233
325
|
}
|
234
326
|
else {
|
235
|
-
ruby_xfree(evlist);
|
236
327
|
rb_sys_fail("epoll_wait() was failed");
|
237
328
|
}
|
238
329
|
}
|
@@ -240,62 +331,110 @@ RETRY:
|
|
240
331
|
ready_evlist = rb_ary_new_capa(ready);
|
241
332
|
for (i = 0; i < ready; i++) {
|
242
333
|
event = rb_obj_alloc(cIO_Epoll_Event);
|
243
|
-
RSTRUCT_SET(event,
|
244
|
-
RSTRUCT_SET(event,
|
334
|
+
RSTRUCT_SET(event, EPOLL_EVENT_DATA, (VALUE) evlist[i].data.ptr);
|
335
|
+
RSTRUCT_SET(event, EPOLL_EVENT_EVENTS, LONG2FIX(evlist[i].events));
|
245
336
|
rb_ary_store(ready_evlist, i, event);
|
246
337
|
}
|
247
|
-
ruby_xfree(evlist);
|
248
338
|
return ready_evlist;
|
249
339
|
}
|
250
340
|
|
251
341
|
static VALUE
|
252
|
-
|
342
|
+
rb_epoll_closed_p(VALUE self)
|
253
343
|
{
|
254
344
|
struct Epoll *ptr = get_epoll(self);
|
255
|
-
|
256
|
-
epoll_fd_close(ptr->epfd);
|
257
|
-
ptr->epfd = -1;
|
258
|
-
return Qnil;
|
345
|
+
return 0 <= ptr->epfd ? Qfalse : Qtrue;
|
259
346
|
}
|
260
347
|
|
261
348
|
static VALUE
|
262
|
-
|
349
|
+
rb_epoll_size(VALUE self)
|
263
350
|
{
|
264
351
|
struct Epoll *ptr = get_epoll(self);
|
265
|
-
return
|
352
|
+
return INT2FIX(ptr->ev_len);
|
266
353
|
}
|
267
354
|
|
355
|
+
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(FD_CLOEXEC)
|
356
|
+
|
268
357
|
static VALUE
|
269
|
-
|
358
|
+
rb_epoll_close_on_exec_p(VALUE self)
|
270
359
|
{
|
271
360
|
struct Epoll *ptr = get_epoll(self);
|
272
|
-
|
361
|
+
int ret;
|
362
|
+
|
363
|
+
epoll_check_closed(ptr);
|
364
|
+
|
365
|
+
if ((ret = fcntl(ptr->epfd, F_GETFD)) == -1)
|
366
|
+
rb_sys_fail("fcntl");
|
367
|
+
|
368
|
+
if (ret & FD_CLOEXEC)
|
369
|
+
return Qtrue;
|
370
|
+
else
|
371
|
+
return Qfalse;
|
372
|
+
}
|
373
|
+
|
374
|
+
#else
|
375
|
+
#define rb_epoll_close_on_exec_p rb_f_notimplement
|
376
|
+
#endif
|
377
|
+
|
378
|
+
#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
379
|
+
|
380
|
+
static VALUE
|
381
|
+
rb_epoll_set_close_on_exec(VALUE self, VALUE b)
|
382
|
+
{
|
383
|
+
struct Epoll *ptr = get_epoll(self);
|
384
|
+
int flag = RTEST(b) ? FD_CLOEXEC : 0;
|
385
|
+
int ret;
|
386
|
+
|
387
|
+
epoll_check_closed(ptr);
|
388
|
+
|
389
|
+
if ((ret = fcntl(ptr->epfd, F_GETFD)) == -1)
|
390
|
+
rb_sys_fail("fcntl");
|
391
|
+
|
392
|
+
if ((ret & FD_CLOEXEC) != flag) {
|
393
|
+
ret = (ret & ~FD_CLOEXEC) | flag;
|
394
|
+
if (fcntl(ptr->epfd, F_SETFD, ret) == -1)
|
395
|
+
rb_sys_fail("fcntl");
|
396
|
+
}
|
397
|
+
return Qnil;
|
273
398
|
}
|
274
399
|
|
400
|
+
#else
|
401
|
+
#define rb_epoll_set_close_on_exec rb_f_notimplement
|
402
|
+
#endif
|
403
|
+
|
404
|
+
#endif // HAVE_SYS_EPOLL_H
|
405
|
+
|
275
406
|
void
|
276
407
|
Init_epoll()
|
277
408
|
{
|
409
|
+
#ifdef HAVE_SYS_EPOLL_H
|
278
410
|
cIO_Epoll = rb_define_class_under(rb_cIO, "Epoll", rb_cObject);
|
279
|
-
cIO_Epoll_Event = rb_struct_define_under(cIO_Epoll, "Event", "data", "events", NULL);
|
280
411
|
rb_define_alloc_func(cIO_Epoll, rb_epoll_allocate);
|
281
|
-
|
412
|
+
rb_define_singleton_method(cIO_Epoll, "new", rb_epoll_s_new, 0);
|
282
413
|
rb_define_method(cIO_Epoll, "initialize", rb_epoll_initialize, 0);
|
414
|
+
rb_define_method(cIO_Epoll, "initialize_copy", rb_epoll_initialize_copy, 1);
|
415
|
+
rb_define_method(cIO_Epoll, "inspect", rb_epoll_inspect, 0);
|
283
416
|
rb_define_method(cIO_Epoll, "ctl", rb_epoll_ctl, -1);
|
284
417
|
rb_define_method(cIO_Epoll, "wait", rb_epoll_wait, -1);
|
285
418
|
rb_define_method(cIO_Epoll, "fileno", rb_epoll_fileno, 0);
|
286
419
|
rb_define_method(cIO_Epoll, "close", rb_epoll_close, 0);
|
287
420
|
rb_define_method(cIO_Epoll, "closed?", rb_epoll_closed_p, 0);
|
288
|
-
rb_define_method(cIO_Epoll, "
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
rb_define_const(
|
294
|
-
rb_define_const(
|
295
|
-
rb_define_const(
|
296
|
-
rb_define_const(
|
297
|
-
rb_define_const(
|
298
|
-
rb_define_const(
|
299
|
-
rb_define_const(
|
300
|
-
rb_define_const(
|
421
|
+
rb_define_method(cIO_Epoll, "size", rb_epoll_size, 0);
|
422
|
+
rb_define_method(cIO_Epoll, "close_on_exec?", rb_epoll_close_on_exec_p, 0);
|
423
|
+
rb_define_method(cIO_Epoll, "close_on_exec=", rb_epoll_set_close_on_exec, 1);
|
424
|
+
|
425
|
+
cIO_Epoll_Constants = rb_define_module_under(cIO_Epoll, "Constants");
|
426
|
+
rb_define_const(cIO_Epoll_Constants, "IN", INT2FIX(EPOLLIN));
|
427
|
+
rb_define_const(cIO_Epoll_Constants, "PRI", INT2FIX(EPOLLPRI));
|
428
|
+
rb_define_const(cIO_Epoll_Constants, "RDHUP", INT2FIX(EPOLLRDHUP));
|
429
|
+
rb_define_const(cIO_Epoll_Constants, "OUT", INT2FIX(EPOLLOUT));
|
430
|
+
rb_define_const(cIO_Epoll_Constants, "ET", INT2FIX(EPOLLET));
|
431
|
+
rb_define_const(cIO_Epoll_Constants, "ONESHOT", INT2FIX(EPOLLONESHOT));
|
432
|
+
rb_define_const(cIO_Epoll_Constants, "ERR", INT2FIX(EPOLLERR));
|
433
|
+
rb_define_const(cIO_Epoll_Constants, "HUP", INT2FIX(EPOLLHUP));
|
434
|
+
rb_define_const(cIO_Epoll_Constants, "CTL_ADD", INT2FIX(EPOLL_CTL_ADD));
|
435
|
+
rb_define_const(cIO_Epoll_Constants, "CTL_MOD", INT2FIX(EPOLL_CTL_MOD));
|
436
|
+
rb_define_const(cIO_Epoll_Constants, "CTL_DEL", INT2FIX(EPOLL_CTL_DEL));
|
437
|
+
|
438
|
+
cIO_Epoll_Event = rb_struct_define_under(cIO_Epoll, "Event", "data", "events", NULL);
|
439
|
+
#endif
|
301
440
|
}
|
data/ext/io/epoll/extconf.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
3
|
if !have_header("sys/epoll.h")
|
4
|
-
puts "***
|
5
|
-
|
4
|
+
puts "[31m*** complie error: gem 'io-epoll' must be installed <sys/epoll.h>. ***[m"
|
5
|
+
puts "[31m*** you can require 'io/epoll'. But, you can not use IO::Epoll APIs. ***[m"
|
6
6
|
end
|
7
|
+
have_func("epoll_create1", "sys/epoll.h")
|
7
8
|
create_makefile('io/epoll/epoll')
|
data/io-epoll.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "io-epoll"
|
3
|
-
spec.version = "0.
|
3
|
+
spec.version = "0.2.0"
|
4
4
|
spec.authors = ["ksss"]
|
5
5
|
spec.email = ["co000ri@gmail.com"]
|
6
|
-
spec.summary = %q{
|
7
|
-
spec.description = %q{
|
6
|
+
spec.summary = %q{A Ruby binding for epoll(7)}
|
7
|
+
spec.description = %q{A Ruby binding for epoll(7)}
|
8
8
|
spec.homepage = "https://github.com/ksss/io-epoll"
|
9
9
|
spec.license = "MIT"
|
10
10
|
|
data/lib/io/epoll.rb
CHANGED
@@ -2,20 +2,24 @@ require 'io/epoll/epoll'
|
|
2
2
|
|
3
3
|
class IO
|
4
4
|
class Epoll
|
5
|
+
include Epoll::Constants
|
6
|
+
|
5
7
|
class << self
|
6
8
|
alias create new
|
7
9
|
end
|
8
10
|
|
11
|
+
alias length size
|
12
|
+
|
9
13
|
def add(io, events)
|
10
|
-
ctl
|
14
|
+
ctl CTL_ADD, io, events
|
11
15
|
end
|
12
16
|
|
13
17
|
def mod(io, events)
|
14
|
-
ctl
|
18
|
+
ctl CTL_MOD, io, events
|
15
19
|
end
|
16
20
|
|
17
21
|
def del(io)
|
18
|
-
ctl
|
22
|
+
ctl CTL_DEL, io
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
data/test/test_epoll.rb
CHANGED
@@ -8,6 +8,44 @@ class TestIOEpoll < Test::Unit::TestCase
|
|
8
8
|
assert_instance_of(IO::Epoll, IO::Epoll.create);
|
9
9
|
end
|
10
10
|
|
11
|
+
def test_create_with_block
|
12
|
+
instance = nil
|
13
|
+
ret_val = IO::Epoll.create do |ep|
|
14
|
+
instance = ep
|
15
|
+
assert { instance.closed? == false }
|
16
|
+
:block_end
|
17
|
+
end
|
18
|
+
assert { instance.kind_of?(IO::Epoll) == true }
|
19
|
+
assert { instance.closed? == true }
|
20
|
+
assert { ret_val == :block_end }
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_create_with_block_ensure_close
|
24
|
+
instance = nil
|
25
|
+
catch do |ok|
|
26
|
+
IO::Epoll.create do |ep|
|
27
|
+
instance = ep
|
28
|
+
throw ok
|
29
|
+
end
|
30
|
+
end
|
31
|
+
assert { instance.closed? == true }
|
32
|
+
|
33
|
+
assert_nothing_raised do
|
34
|
+
IO::Epoll.create do |ep|
|
35
|
+
ep.close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_inspect
|
41
|
+
IO::Epoll.create do |ep|
|
42
|
+
fd = ep.fileno
|
43
|
+
assert { "#<IO::Epoll:fd #{fd}>" == ep.inspect }
|
44
|
+
ep.close
|
45
|
+
assert { "#<IO::Epoll: (closed)>" == ep.inspect }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
11
49
|
def test_fileno
|
12
50
|
ep = IO::Epoll.create
|
13
51
|
assert { 0 < ep.fileno }
|
@@ -16,14 +54,15 @@ class TestIOEpoll < Test::Unit::TestCase
|
|
16
54
|
end
|
17
55
|
|
18
56
|
def test_ctl
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
57
|
+
IO::Epoll.create do |ep|
|
58
|
+
io = IO.new(1, 'w')
|
59
|
+
assert { ep == ep.ctl(IO::Epoll::CTL_ADD, io , IO::Epoll::OUT) }
|
60
|
+
assert_raise(ArgumentError) { ep.ctl }
|
61
|
+
assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD) }
|
62
|
+
assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD, io) }
|
63
|
+
assert_raise(ArgumentError) { ep.ctl(-1, io) }
|
64
|
+
assert_raise(TypeError) { ep.ctl(nil, nil, nil) }
|
65
|
+
end
|
27
66
|
end
|
28
67
|
|
29
68
|
def test_add
|
@@ -56,38 +95,56 @@ class TestIOEpoll < Test::Unit::TestCase
|
|
56
95
|
end
|
57
96
|
|
58
97
|
def test_wait
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
98
|
+
IO::Epoll.create do |ep|
|
99
|
+
io = IO.new(1, 'w')
|
100
|
+
ep.add(io, IO::Epoll::IN|IO::Epoll::PRI|IO::Epoll::RDHUP|IO::Epoll::ET|IO::Epoll::OUT)
|
101
|
+
evlist = ep.wait
|
102
|
+
assert { [IO::Epoll::Event.new(io, IO::Epoll::OUT)] == evlist }
|
103
|
+
assert_instance_of(IO, evlist[0].data)
|
104
|
+
assert_instance_of(Fixnum, evlist[0].events)
|
105
|
+
assert_raise(TypeError) { ep.wait(nil) }
|
106
|
+
assert_raise(IOError) { IO::Epoll.create.wait }
|
107
|
+
end
|
68
108
|
end
|
69
109
|
|
70
110
|
def test_wait_with_timeout
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
111
|
+
IO::Epoll.create do |ep|
|
112
|
+
io = IO.new(1, 'w')
|
113
|
+
ep.add(io, IO::Epoll::IN)
|
114
|
+
assert { [] == ep.wait(0) }
|
115
|
+
assert { [] == ep.wait(1) }
|
116
|
+
assert_raise(TimeoutError) do
|
117
|
+
timeout(0.01) { ep.wait(-1) }
|
118
|
+
end
|
78
119
|
end
|
79
120
|
end
|
80
121
|
|
81
122
|
def test_size
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
123
|
+
IO::Epoll.create do |ep|
|
124
|
+
io = IO.new(0, 'r')
|
125
|
+
ep.add(io, IO::Epoll::IN)
|
126
|
+
assert { 1 == ep.size }
|
127
|
+
ep.del(io)
|
128
|
+
assert { 0 == ep.size }
|
129
|
+
end
|
88
130
|
end
|
89
131
|
|
90
|
-
def
|
132
|
+
def test_close
|
133
|
+
assert_nothing_raised do
|
134
|
+
fileno = nil
|
135
|
+
10.times do
|
136
|
+
ep = IO::Epoll.create
|
137
|
+
fileno = ep.fileno unless fileno
|
138
|
+
assert { fileno == ep.fileno }
|
139
|
+
ep.close
|
140
|
+
|
141
|
+
IO::Epoll.create do
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_closed?
|
91
148
|
ep = IO::Epoll.create
|
92
149
|
assert { false == ep.closed? }
|
93
150
|
assert { nil == ep.close }
|
@@ -95,14 +152,43 @@ class TestIOEpoll < Test::Unit::TestCase
|
|
95
152
|
assert { true == ep.closed? }
|
96
153
|
end
|
97
154
|
|
155
|
+
def test_dup
|
156
|
+
IO::Epoll.create do |ep|
|
157
|
+
io = IO.new(1, 'w')
|
158
|
+
ep.add(io, IO::Epoll::OUT)
|
159
|
+
dup = ep.dup
|
160
|
+
assert { ep != dup }
|
161
|
+
assert { ep.fileno != dup.fileno }
|
162
|
+
assert { ep.size == dup.size }
|
163
|
+
assert { [IO::Epoll::Event.new(io, IO::Epoll::OUT)] == dup.wait }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_close_on_exec
|
168
|
+
return unless defined? Fcntl::FD_CLOEXEC
|
169
|
+
IO::Epoll.create do |ep|
|
170
|
+
assert { true == ep.close_on_exec? }
|
171
|
+
ep.close_on_exec = false
|
172
|
+
assert { false == ep.close_on_exec? }
|
173
|
+
ep.close_on_exec = true
|
174
|
+
assert { true == ep.close_on_exec? }
|
175
|
+
ep.close_on_exec = false
|
176
|
+
assert { false == ep.close_on_exec? }
|
177
|
+
ep.close
|
178
|
+
assert_raise { ep.close_on_exec = true }
|
179
|
+
assert_raise { ep.close_on_exec? }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
98
183
|
def test_thread
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
184
|
+
IO::Epoll.create do |ep|
|
185
|
+
io = IO.new(1, 'w')
|
186
|
+
ep.add(io, IO::Epoll::OUT)
|
187
|
+
ret = nil
|
188
|
+
Thread.start {
|
189
|
+
ret = ep.wait
|
190
|
+
}.join
|
191
|
+
assert { io == ret[0].data }
|
192
|
+
end
|
107
193
|
end
|
108
194
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-epoll
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ksss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
description:
|
69
|
+
description: A Ruby binding for epoll(7)
|
70
70
|
email:
|
71
71
|
- co000ri@gmail.com
|
72
72
|
executables: []
|
@@ -110,6 +110,6 @@ rubyforge_project:
|
|
110
110
|
rubygems_version: 2.4.1
|
111
111
|
signing_key:
|
112
112
|
specification_version: 4
|
113
|
-
summary:
|
113
|
+
summary: A Ruby binding for epoll(7)
|
114
114
|
test_files:
|
115
115
|
- test/test_epoll.rb
|