io-epoll 0.0.1 → 0.0.2

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: c4f6bb1879b7524f23926e37da7c5fe53dec55b4
4
- data.tar.gz: a0b1c12561b78414aa9f9fb3b567be508daf2685
3
+ metadata.gz: f1d5379f3b1a1f7630975f462c9580f0156d53b0
4
+ data.tar.gz: f9627c3a392a839c64b204aeae939d1fbf8da753
5
5
  SHA512:
6
- metadata.gz: be6db2e498ced13bb8d5219f1d2ab60386cd00b8d3311887ad9dbf13feae7d902a59e8a096103cb16007a4c6944020ba58de827f46691e30316c7db9fa004c65
7
- data.tar.gz: 736de758a7a0a143b51fca8831d5679bac11c66033e40c6d6cfcba14fc5cceefabe1a5a649007c13dfd5a66b884094090b3c4864931b1fe3aaae41ece987b946
6
+ metadata.gz: 10dfbf4366e5c54dbad66a2bf33d822851d9e2481eda47007348b7446c7939433efd0272bb65a918bec2c6c4486b57a9f1a067c045222d84eeb9831852bf1cd4
7
+ data.tar.gz: 0bf8d0e53cfb0bd207ed962341481c30c561301752b8f50e4a7767adef959950cd80f4d55644eddcdd7a09711804ffa6e8c2e8b3c1cb7aa5ac7fced2c23e46f5
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.4
4
+ - 2.2.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- io-epoll (0.0.1)
4
+ io-epoll (0.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  io-epoll
2
2
  ===
3
3
 
4
+ [![Build Status](https://travis-ci.org/ksss/io-epoll.svg?branch=master)](https://travis-ci.org/ksss/io-epoll)
5
+
4
6
  An experimental binding of epoll(7).
5
7
 
6
8
  **epoll(7)** can use Linux only. (because must be installed sys/epoll.h)
@@ -14,24 +16,32 @@ IO.epoll([io1, io2, io3], Epoll::IN) do |ev|
14
16
  # ev is IO::Epoll::Event object like `struct epoll_event`
15
17
  # it's have data and events properties
16
18
 
17
- # events is event flag bits (Fixnum)
19
+ # IO::Epoll::Event#events is event flag bits (Fixnum)
18
20
  events = ev.events
19
21
 
20
- # data is notificated IO (IO)
22
+ # IO::Epoll::Event#data is notified IO (IO)
21
23
  data = ev.data
22
24
  end
23
25
 
26
+ # or
27
+
28
+ # evlist is Array of IO::Epoll::Event
29
+ # it's just short hand for epoll_create(2) -> epoll_ctl(2) -> epoll_wait(2)
30
+ evlist = IO.epoll([io1, io2, io3], Epoll::IN)
31
+
24
32
  # on other way, you can make instance of IO::Epoll
25
33
 
26
34
  Epoll = IO::Epoll
27
35
 
28
36
  # IO::Epoll.create
29
- # run epoll_create(2)
37
+ # call epoll_create(2)
30
38
  # it's just alias of `new`
39
+ # Epoll object stock a File Descriptor returned by epoll_create(2)
40
+ # return: instance of IO::Epoll
31
41
  epoll = Epoll.create
32
42
 
33
43
  # IO::Epoll#ctl(option, io, flag)
34
- # run epoll_ctl(2)
44
+ # call epoll_ctl(2)
35
45
  # option: you can choice epoll_ctl option in CTL_ADD, CTL_MOD and CTL_DEL.
36
46
  # CTL_ADD: add io list to watching for created epoll fd
37
47
  # CTL_MOD: you can change io events
@@ -39,6 +49,7 @@ epoll = Epoll.create
39
49
  # io: set an IO object for watching.
40
50
  # flag: set flag bits like Epoll::IN|Epoll::OUT|Epoll::ONESHOT etc...
41
51
  # see also man epoll_ctl(2)
52
+ # return: self
42
53
  epoll.ctl(Epoll::CTL_ADD, io, Epoll::IN)
43
54
 
44
55
  # and you can use short way
@@ -47,13 +58,35 @@ epoll.mod(io, Epoll::OUT) # same way to epoll.ctl(Epoll::CTL_MOD, io, Epoll::IN)
47
58
  epoll.del(io) # same way to epoll.ctl(Epoll::CTL_DEL, io)
48
59
 
49
60
  # IO::Epoll#wait(timeout=-1)
50
- # run epoll_wait(2)
61
+ # call epoll_wait(2)
51
62
  # timeout = -1: block until receive event or signals
52
63
  # timeout = 0: return all io's can I/O on non block
53
64
  # timeout > 0: block when timeout pass miri second or receive events or signals
65
+ # return: Array of IO::Epoll::Event
54
66
  evlist = epoll.wait
67
+
68
+ # you can close File Descriptor for epoll when finish to use
69
+ epoll.close #=> nil
70
+
71
+ # and you can check closed
72
+ epoll.closed? #=> true
55
73
  ```
56
74
 
75
+ ## Event flags
76
+
77
+ event flags|ctl|wait|description
78
+ ---|---|---|---
79
+ **IO::Epoll::IN**|o|o|readable
80
+ **IO::Epoll::PRI**|o|o|high priority read
81
+ **IO::Epoll::HUP**|o|o|peer socket was shutdown
82
+ **IO::Epoll::OUT**|o|o|writable
83
+ **IO::Epoll::ET**|o|x|use edge trigger
84
+ **IO::Epoll:ONESHOT**|o|x|auto watching stop when notified(but stay in list)
85
+ **IO::Epoll::ERR**|x|o|raise error
86
+ **IO::Epoll::HUP**|x|o|raise hang up
87
+
88
+ see also **man epoll(7)**
89
+
57
90
  ## Installation
58
91
 
59
92
  Add this line to your application's Gemfile:
data/Rakefile CHANGED
@@ -2,10 +2,11 @@ require "bundler/gem_tasks"
2
2
  require 'rake/extensiontask'
3
3
  require 'rake/testtask'
4
4
 
5
+ task :default => [:compile, :test]
6
+
5
7
  Rake::ExtensionTask.new('epoll') do |ext|
6
8
  ext.name = 'epoll'
7
9
  ext.ext_dir = 'ext/io/epoll'
8
10
  ext.lib_dir = 'lib/io/epoll'
9
11
  end
10
12
  Rake::TestTask.new {|t| t.libs << 'test'}
11
-
data/ext/io/epoll/epoll.c CHANGED
@@ -89,24 +89,26 @@ rb_epoll_ctl(int argc, VALUE *argv, VALUE self)
89
89
  VALUE flag;
90
90
  VALUE io;
91
91
  VALUE events;
92
+ rb_io_t *fptr;
92
93
  int fd;
93
94
 
94
95
  switch (rb_scan_args(argc, argv, "21", &flag, &io, &events)) {
95
96
  case 2:
96
- if (FIX2INT(flag) != EPOLL_CTL_DEL) {
97
+ if (FIX2INT(flag) != EPOLL_CTL_DEL)
97
98
  rb_raise(rb_eArgError, "too few argument for CTL_ADD or CTL_MOD");
98
- }
99
99
  break;
100
100
  case 3:
101
- if (FIX2INT(flag) != EPOLL_CTL_ADD && FIX2INT(flag) != EPOLL_CTL_MOD) {
101
+ if (FIX2INT(flag) != EPOLL_CTL_ADD && FIX2INT(flag) != EPOLL_CTL_MOD)
102
102
  rb_raise(rb_eArgError, "too many argument for CTL_DEL");
103
- }
104
- ev.events = FIX2INT(events);
103
+ if ((FIX2LONG(events) & (EPOLLIN|EPOLLPRI|EPOLLRDHUP|EPOLLOUT|EPOLLET|EPOLLONESHOT)) == 0)
104
+ rb_raise(rb_eIOError, "undefined events");
105
+ ev.events = FIX2LONG(events);
105
106
  ev.data.ptr = (void*)io;
106
107
  break;
107
108
  }
108
109
 
109
- fd = RFILE(io)->fptr->fd;
110
+ GetOpenFile(rb_io_get_io(io), fptr);
111
+ fd = fptr->fd;
110
112
 
111
113
  if (epoll_ctl(ptr->epfd, FIX2INT(flag), fd, &ev) == -1) {
112
114
  char buf[128];
@@ -148,15 +150,18 @@ rb_epoll_wait(int argc, VALUE *argv, VALUE self)
148
150
  {
149
151
  struct Epoll *ptr = get_epoll(self);
150
152
  VALUE ready_evlist;
153
+ VALUE cEvent;
151
154
  VALUE event;
152
155
  struct epoll_event *evlist;
153
156
  int i, ready;
154
157
  int timeout = -1;
155
158
  struct epoll_wait_args data;
156
159
 
157
- if (argc == 1) {
160
+ if (argc == 1)
158
161
  timeout = FIX2INT(argv[0]);
159
- }
162
+ if (ptr->ev_len <= 0)
163
+ rb_raise(rb_eIOError, "empty interest list");
164
+
160
165
  evlist = ruby_xmalloc(ptr->ev_len * sizeof(struct epoll_event));
161
166
 
162
167
  data.ptr = ptr;
@@ -176,10 +181,11 @@ RETRY:
176
181
  }
177
182
 
178
183
  ready_evlist = rb_ary_new_capa(ready);
184
+ cEvent = rb_path2class("IO::Epoll::Event");
179
185
  for (i = 0; i < ready; i++) {
180
- event = rb_obj_alloc(rb_path2class("IO::Epoll::Event"));
186
+ event = rb_obj_alloc(cEvent);
181
187
  RSTRUCT_SET(event, 0, (VALUE) evlist[i].data.ptr);
182
- RSTRUCT_SET(event, 1, INT2FIX(evlist[i].events));
188
+ RSTRUCT_SET(event, 1, LONG2FIX(evlist[i].events));
183
189
  rb_ary_store(ready_evlist, i, event);
184
190
  }
185
191
  ruby_xfree(evlist);
data/io-epoll.gemspec CHANGED
@@ -1,11 +1,11 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "io-epoll"
3
- spec.version = "0.0.1"
3
+ spec.version = "0.0.2"
4
4
  spec.authors = ["ksss"]
5
5
  spec.email = ["co000ri@gmail.com"]
6
6
  spec.summary = %q{An experimental binding of epoll(7)}
7
7
  spec.description = %q{An experimental binding of epoll(7)}
8
- spec.homepage = ""
8
+ spec.homepage = "https://github.com/ksss/io-epoll"
9
9
  spec.license = "MIT"
10
10
 
11
11
  spec.files = `git ls-files`.split($/)
data/lib/io/epoll.rb CHANGED
@@ -27,6 +27,7 @@ class IO
27
27
  end
28
28
 
29
29
  def self.epoll(ios, events)
30
+ ios = ios.to_a
30
31
  open_len = ios.length
31
32
  ep = Epoll.create
32
33
  ios.each do |io|
@@ -43,9 +44,11 @@ class IO
43
44
  end
44
45
  end
45
46
  end
46
- nil
47
+ ep.close
47
48
  else
48
- ep.wait
49
+ evlist = ep.wait
50
+ ep.close
51
+ evlist
49
52
  end
50
53
  end
51
54
  end
data/test/test_epoll.rb CHANGED
@@ -5,32 +5,35 @@ require_relative '../lib/io/epoll'
5
5
  class TestIOEpoll < Test::Unit::TestCase
6
6
  def test_initalize
7
7
  assert_instance_of(IO::Epoll, IO::Epoll.new);
8
+ assert_instance_of(IO::Epoll, IO::Epoll.create);
8
9
  end
9
10
 
10
11
  def test_fileno
11
- assert { 0 < IO::Epoll.new.fileno }
12
+ assert { 0 < IO::Epoll.create.fileno }
12
13
  end
13
14
 
14
15
  def test_ctl
15
- ep = IO::Epoll.new
16
+ ep = IO::Epoll.create
16
17
  io = IO.new(1, 'w')
18
+ assert { ep == ep.ctl(IO::Epoll::CTL_ADD, io , IO::Epoll::OUT) }
17
19
  assert_raise(ArgumentError) { ep.ctl }
18
20
  assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD) }
19
21
  assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD, io) }
20
- assert { ep == ep.ctl(IO::Epoll::CTL_ADD, io , IO::Epoll::OUT) }
21
22
  assert_raise(ArgumentError) { ep.ctl(-1, io) }
23
+ assert_raise(TypeError) { ep.ctl(nil, nil, nil) }
22
24
  end
23
25
 
24
26
  def test_add
25
- ep = IO::Epoll.new
27
+ ep = IO::Epoll.create
26
28
  io = IO.new(1, 'w')
27
- assert { ep == ep.add(io, IO::Epoll::OUT) }
29
+ assert_raise(IOError) { ep.add(io, 0) }
30
+ assert { ep == ep.add(io, IO::Epoll::IN|IO::Epoll::PRI|IO::Epoll::RDHUP|IO::Epoll::ET|IO::Epoll::OUT) }
28
31
  ep.close
29
32
  assert_raise(Errno::EBADF) { ep.add(io, IO::Epoll::OUT) }
30
33
  end
31
34
 
32
35
  def test_mod
33
- ep = IO::Epoll.new
36
+ ep = IO::Epoll.create
34
37
  io = IO.new(1, 'w')
35
38
  assert_raise(Errno::ENOENT) { ep.mod(io, IO::Epoll::IN) }
36
39
  ep == ep.add(io, IO::Epoll::OUT)
@@ -40,7 +43,7 @@ class TestIOEpoll < Test::Unit::TestCase
40
43
  end
41
44
 
42
45
  def test_del
43
- ep = IO::Epoll.new
46
+ ep = IO::Epoll.create
44
47
  io = IO.new(1, 'w')
45
48
  assert_raise(Errno::ENOENT) { ep.del(io) }
46
49
  ep.add(io, IO::Epoll::OUT)
@@ -50,15 +53,16 @@ class TestIOEpoll < Test::Unit::TestCase
50
53
  end
51
54
 
52
55
  def test_wait
53
- ep = IO::Epoll.new
54
- io1 = IO.new(1, 'w')
55
- io2 = IO.new(2, 'w')
56
- ep.add(io1, IO::Epoll::OUT)
57
- assert { [IO::Epoll::Event.new(io1, IO::Epoll::OUT)] == ep.wait }
56
+ ep = IO::Epoll.create
57
+ io = IO.new(1, 'w')
58
+ ep.add(io, IO::Epoll::IN|IO::Epoll::PRI|IO::Epoll::RDHUP|IO::Epoll::ET|IO::Epoll::OUT)
59
+ assert { [IO::Epoll::Event.new(io, IO::Epoll::OUT)] == ep.wait }
60
+ assert_raise(TypeError) { ep.wait(nil) }
61
+ assert_raise(IOError) { IO::Epoll.create.wait }
58
62
  end
59
63
 
60
64
  def test_wait_with_timeout
61
- ep = IO::Epoll.new
65
+ ep = IO::Epoll.create
62
66
  io = IO.new(1, 'w')
63
67
  ep.add(io, IO::Epoll::IN)
64
68
  assert { [] == ep.wait(0) }
@@ -69,7 +73,7 @@ class TestIOEpoll < Test::Unit::TestCase
69
73
  end
70
74
 
71
75
  def test_size
72
- ep = IO::Epoll.new
76
+ ep = IO::Epoll.create
73
77
  io = IO.new(0, 'r')
74
78
  ep.add(io, IO::Epoll::IN)
75
79
  assert { 1 == ep.size }
@@ -78,7 +82,7 @@ class TestIOEpoll < Test::Unit::TestCase
78
82
  end
79
83
 
80
84
  def test_close_closed?
81
- ep = IO::Epoll.new
85
+ ep = IO::Epoll.create
82
86
  assert { false == ep.closed? }
83
87
  assert { nil == ep.close }
84
88
  assert_raise(IOError){ ep.close }
@@ -96,6 +100,9 @@ class TestIOEpoll < Test::Unit::TestCase
96
100
  evs = IO.epoll([r], IO::Epoll::IN)
97
101
  assert { 'ok' == evs[0].data.read }
98
102
  assert { false == evs[0].data.closed? }
103
+ assert_raise(IOError) { IO.epoll(nil, nil) }
104
+ assert_raise(IOError) { IO.epoll([], nil) }
105
+ assert_raise(TypeError) { IO.epoll([nil], nil) }
99
106
  end
100
107
 
101
108
  def test_epoll_with_block
@@ -114,7 +121,7 @@ class TestIOEpoll < Test::Unit::TestCase
114
121
  end
115
122
 
116
123
  def test_thread
117
- ep = IO::Epoll.new
124
+ ep = IO::Epoll.create
118
125
  io = IO.new(1, 'w')
119
126
  ep.add(io, IO::Epoll::OUT)
120
127
  ret = nil
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.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-30 00:00:00.000000000 Z
11
+ date: 2014-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,6 +75,7 @@ extensions:
75
75
  extra_rdoc_files: []
76
76
  files:
77
77
  - ".gitignore"
78
+ - ".travis.yml"
78
79
  - Gemfile
79
80
  - Gemfile.lock
80
81
  - LICENSE.txt
@@ -85,7 +86,7 @@ files:
85
86
  - io-epoll.gemspec
86
87
  - lib/io/epoll.rb
87
88
  - test/test_epoll.rb
88
- homepage: ''
89
+ homepage: https://github.com/ksss/io-epoll
89
90
  licenses:
90
91
  - MIT
91
92
  metadata: {}