io-epoll 0.1.0 → 0.2.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.
- 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
|