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 +4 -4
- data/.travis.yml +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +38 -5
- data/Rakefile +2 -1
- data/ext/io/epoll/epoll.c +16 -10
- data/io-epoll.gemspec +2 -2
- data/lib/io/epoll.rb +5 -2
- data/test/test_epoll.rb +23 -16
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1d5379f3b1a1f7630975f462c9580f0156d53b0
|
4
|
+
data.tar.gz: f9627c3a392a839c64b204aeae939d1fbf8da753
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10dfbf4366e5c54dbad66a2bf33d822851d9e2481eda47007348b7446c7939433efd0272bb65a918bec2c6c4486b57a9f1a067c045222d84eeb9831852bf1cd4
|
7
|
+
data.tar.gz: 0bf8d0e53cfb0bd207ed962341481c30c561301752b8f50e4a7767adef959950cd80f4d55644eddcdd7a09711804ffa6e8c2e8b3c1cb7aa5ac7fced2c23e46f5
|
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
io-epoll
|
2
2
|
===
|
3
3
|
|
4
|
+
[](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
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
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
|
-
|
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(
|
186
|
+
event = rb_obj_alloc(cEvent);
|
181
187
|
RSTRUCT_SET(event, 0, (VALUE) evlist[i].data.ptr);
|
182
|
-
RSTRUCT_SET(event, 1,
|
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.
|
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
|
-
|
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.
|
12
|
+
assert { 0 < IO::Epoll.create.fileno }
|
12
13
|
end
|
13
14
|
|
14
15
|
def test_ctl
|
15
|
-
ep = IO::Epoll.
|
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.
|
27
|
+
ep = IO::Epoll.create
|
26
28
|
io = IO.new(1, 'w')
|
27
|
-
|
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.
|
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.
|
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.
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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-
|
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: {}
|