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 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