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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87c51dc70ed31c8d3a34012ce002a0c9c19c7982
4
- data.tar.gz: 92e3c83055ba130342883cb1bb15f9d55bf6c6fd
3
+ metadata.gz: 97d310cf1317528f3b0d1315862f1365a9a3480b
4
+ data.tar.gz: 87e9317da46fa65ad67f9f3dd66a0589ca44adf6
5
5
  SHA512:
6
- metadata.gz: bd0dd5bdd8e4085c8b6be91ba5ddd218d448981cd3365c498c4bd936196da3d9827d639ff1afeccc5c1ecad72f29de6a16933aab90f6c7bef1f5f678b931a857
7
- data.tar.gz: 1eec9c05b0d6e9c6b22fe399992389b62dd92672e65255bcf34d0c1dc4acb8bb6ed46aad0f4a1c1df8424a4d5e567cbee5e226e2c8b2db8e4a4935053192061b
6
+ metadata.gz: c4c7b4cfbf7b113800d952650c8c49948e63ce0c4de8a80be3f2a90ebdfba0cb3b8a0672ed518e853550c13cf48907a31485731c70f494213ffb173c212d01c0
7
+ data.tar.gz: 4769b5237627dbff6621fae9bb9a8044d8560689f684b328ee50c51a90ab45a9a0a3dac1f234d0de73f66f80746141ccf55576085995121a2e35450b0718564d
@@ -2,3 +2,5 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.4
4
4
  - 2.2.0
5
+ os:
6
+ - linux
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- io-epoll (0.1.0)
4
+ io-epoll (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
- epoll.mod(io, Epoll::OUT) # same way to epoll.ctl(Epoll::CTL_MOD, io, Epoll::IN)
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 same as `class Event < Struct.new(:data, :events); end`
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:ONESHOT**|o|x|auto watching stop when notified(but stay in list)
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
- # Fork me !
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 !
@@ -4,6 +4,7 @@ require 'io/epoll'
4
4
  require 'socket'
5
5
 
6
6
  server = TCPServer.open(4000)
7
+ puts "run http://127.0.0.1:4000/"
7
8
 
8
9
  response = [
9
10
  "HTTP/1.0 200 OK\r\n",
@@ -44,4 +45,3 @@ loop do
44
45
  end
45
46
  end
46
47
  end
47
-
@@ -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
- static void
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
- rb_thread_fd_close(epfd);
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
- epfd = epoll_create(1);
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
- VALUE evlist = rb_ivar_get(self, rb_intern("evlist"));
119
- rb_ary_push(evlist, io);
120
- rb_ivar_set(self, rb_intern("evlist"), evlist);
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->ptr->ev_len, data->timeout);
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
- if (argc == 1)
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, 0, (VALUE) evlist[i].data.ptr);
244
- RSTRUCT_SET(event, 1, LONG2FIX(evlist[i].events));
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
- rb_epoll_close(VALUE self)
342
+ rb_epoll_closed_p(VALUE self)
253
343
  {
254
344
  struct Epoll *ptr = get_epoll(self);
255
- epoll_check_closed(ptr);
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
- rb_epoll_closed_p(VALUE self)
349
+ rb_epoll_size(VALUE self)
263
350
  {
264
351
  struct Epoll *ptr = get_epoll(self);
265
- return 0 <= ptr->epfd ? Qfalse : Qtrue;
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
- rb_epoll_length(VALUE self)
358
+ rb_epoll_close_on_exec_p(VALUE self)
270
359
  {
271
360
  struct Epoll *ptr = get_epoll(self);
272
- return INT2FIX(ptr->ev_len);
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, "length", rb_epoll_length, 0);
289
- rb_define_alias(cIO_Epoll, "size", "length");
290
- rb_define_const(cIO_Epoll, "IN", INT2FIX(EPOLLIN));
291
- rb_define_const(cIO_Epoll, "PRI", INT2FIX(EPOLLPRI));
292
- rb_define_const(cIO_Epoll, "RDHUP", INT2FIX(EPOLLRDHUP));
293
- rb_define_const(cIO_Epoll, "OUT", INT2FIX(EPOLLOUT));
294
- rb_define_const(cIO_Epoll, "ET", INT2FIX(EPOLLET));
295
- rb_define_const(cIO_Epoll, "ONESHOT", INT2FIX(EPOLLONESHOT));
296
- rb_define_const(cIO_Epoll, "ERR", INT2FIX(EPOLLERR));
297
- rb_define_const(cIO_Epoll, "HUP", INT2FIX(EPOLLHUP));
298
- rb_define_const(cIO_Epoll, "CTL_ADD", INT2FIX(EPOLL_CTL_ADD));
299
- rb_define_const(cIO_Epoll, "CTL_MOD", INT2FIX(EPOLL_CTL_MOD));
300
- rb_define_const(cIO_Epoll, "CTL_DEL", INT2FIX(EPOLL_CTL_DEL));
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
  }
@@ -1,7 +1,8 @@
1
1
  require 'mkmf'
2
2
 
3
3
  if !have_header("sys/epoll.h")
4
- puts "*** err: <sys/epoll.h> header must be installed ***"
5
- exit 1
4
+ puts "*** complie error: gem 'io-epoll' must be installed <sys/epoll.h>. ***"
5
+ puts "*** you can require 'io/epoll'. But, you can not use IO::Epoll APIs. ***"
6
6
  end
7
+ have_func("epoll_create1", "sys/epoll.h")
7
8
  create_makefile('io/epoll/epoll')
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "io-epoll"
3
- spec.version = "0.1.0"
3
+ spec.version = "0.2.0"
4
4
  spec.authors = ["ksss"]
5
5
  spec.email = ["co000ri@gmail.com"]
6
- spec.summary = %q{An experimental binding of epoll(7)}
7
- spec.description = %q{An experimental binding of epoll(7)}
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
 
@@ -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(CTL_ADD, io, events)
14
+ ctl CTL_ADD, io, events
11
15
  end
12
16
 
13
17
  def mod(io, events)
14
- ctl(CTL_MOD, io, events)
18
+ ctl CTL_MOD, io, events
15
19
  end
16
20
 
17
21
  def del(io)
18
- ctl(CTL_DEL, io)
22
+ ctl CTL_DEL, io
19
23
  end
20
24
  end
21
25
  end
@@ -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
- ep = IO::Epoll.create
20
- io = IO.new(1, 'w')
21
- assert { ep == ep.ctl(IO::Epoll::CTL_ADD, io , IO::Epoll::OUT) }
22
- assert_raise(ArgumentError) { ep.ctl }
23
- assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD) }
24
- assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD, io) }
25
- assert_raise(ArgumentError) { ep.ctl(-1, io) }
26
- assert_raise(TypeError) { ep.ctl(nil, nil, nil) }
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
- ep = IO::Epoll.create
60
- io = IO.new(1, 'w')
61
- ep.add(io, IO::Epoll::IN|IO::Epoll::PRI|IO::Epoll::RDHUP|IO::Epoll::ET|IO::Epoll::OUT)
62
- evlist = ep.wait
63
- assert { [IO::Epoll::Event.new(io, IO::Epoll::OUT)] == evlist }
64
- assert_instance_of(IO, evlist[0].data)
65
- assert_instance_of(Fixnum, evlist[0].events)
66
- assert_raise(TypeError) { ep.wait(nil) }
67
- assert_raise(IOError) { IO::Epoll.create.wait }
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
- ep = IO::Epoll.create
72
- io = IO.new(1, 'w')
73
- ep.add(io, IO::Epoll::IN)
74
- assert { [] == ep.wait(0) }
75
- assert { [] == ep.wait(1) }
76
- assert_raise(TimeoutError) do
77
- timeout(0.01) { ep.wait(-1) }
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
- ep = IO::Epoll.create
83
- io = IO.new(0, 'r')
84
- ep.add(io, IO::Epoll::IN)
85
- assert { 1 == ep.size }
86
- ep.del(io)
87
- assert { 0 == ep.size }
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 test_close_closed?
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
- ep = IO::Epoll.create
100
- io = IO.new(1, 'w')
101
- ep.add(io, IO::Epoll::OUT)
102
- ret = nil
103
- Thread.start {
104
- ret = ep.wait
105
- }.join
106
- assert { io == ret[0].data }
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.1.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-02 00:00:00.000000000 Z
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: An experimental binding of epoll(7)
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: An experimental binding of epoll(7)
113
+ summary: A Ruby binding for epoll(7)
114
114
  test_files:
115
115
  - test/test_epoll.rb