io-epoll 0.0.1
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 +7 -0
- data/.gitignore +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +11 -0
- data/ext/io/epoll/epoll.c +231 -0
- data/ext/io/epoll/extconf.rb +7 -0
- data/io-epoll.gemspec +21 -0
- data/lib/io/epoll.rb +51 -0
- data/test/test_epoll.rb +126 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c4f6bb1879b7524f23926e37da7c5fe53dec55b4
|
4
|
+
data.tar.gz: a0b1c12561b78414aa9f9fb3b567be508daf2685
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be6db2e498ced13bb8d5219f1d2ab60386cd00b8d3311887ad9dbf13feae7d902a59e8a096103cb16007a4c6944020ba58de827f46691e30316c7db9fa004c65
|
7
|
+
data.tar.gz: 736de758a7a0a143b51fca8831d5679bac11c66033e40c6d6cfcba14fc5cceefabe1a5a649007c13dfd5a66b884094090b3c4864931b1fe3aaae41ece987b946
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
io-epoll (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
power_assert (0.1.3)
|
10
|
+
rake (10.3.2)
|
11
|
+
rake-compiler (0.8.3)
|
12
|
+
rake
|
13
|
+
test-unit (3.0.1)
|
14
|
+
power_assert
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
bundler
|
21
|
+
io-epoll!
|
22
|
+
rake
|
23
|
+
rake-compiler
|
24
|
+
test-unit
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 ksss
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
io-epoll
|
2
|
+
===
|
3
|
+
|
4
|
+
An experimental binding of epoll(7).
|
5
|
+
|
6
|
+
**epoll(7)** can use Linux only. (because must be installed sys/epoll.h)
|
7
|
+
|
8
|
+
# Usage
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
require 'io/epoll'
|
12
|
+
|
13
|
+
IO.epoll([io1, io2, io3], Epoll::IN) do |ev|
|
14
|
+
# ev is IO::Epoll::Event object like `struct epoll_event`
|
15
|
+
# it's have data and events properties
|
16
|
+
|
17
|
+
# events is event flag bits (Fixnum)
|
18
|
+
events = ev.events
|
19
|
+
|
20
|
+
# data is notificated IO (IO)
|
21
|
+
data = ev.data
|
22
|
+
end
|
23
|
+
|
24
|
+
# on other way, you can make instance of IO::Epoll
|
25
|
+
|
26
|
+
Epoll = IO::Epoll
|
27
|
+
|
28
|
+
# IO::Epoll.create
|
29
|
+
# run epoll_create(2)
|
30
|
+
# it's just alias of `new`
|
31
|
+
epoll = Epoll.create
|
32
|
+
|
33
|
+
# IO::Epoll#ctl(option, io, flag)
|
34
|
+
# run epoll_ctl(2)
|
35
|
+
# option: you can choice epoll_ctl option in CTL_ADD, CTL_MOD and CTL_DEL.
|
36
|
+
# CTL_ADD: add io list to watching for created epoll fd
|
37
|
+
# CTL_MOD: you can change io events
|
38
|
+
# CTL_DEL: delete io in watching list
|
39
|
+
# io: set an IO object for watching.
|
40
|
+
# flag: set flag bits like Epoll::IN|Epoll::OUT|Epoll::ONESHOT etc...
|
41
|
+
# see also man epoll_ctl(2)
|
42
|
+
epoll.ctl(Epoll::CTL_ADD, io, Epoll::IN)
|
43
|
+
|
44
|
+
# and you can use short way
|
45
|
+
epoll.add(io, Epoll::IN) # same way to epoll.ctl(Epoll::CTL_ADD, io, Epoll::IN)
|
46
|
+
epoll.mod(io, Epoll::OUT) # same way to epoll.ctl(Epoll::CTL_MOD, io, Epoll::IN)
|
47
|
+
epoll.del(io) # same way to epoll.ctl(Epoll::CTL_DEL, io)
|
48
|
+
|
49
|
+
# IO::Epoll#wait(timeout=-1)
|
50
|
+
# run epoll_wait(2)
|
51
|
+
# timeout = -1: block until receive event or signals
|
52
|
+
# timeout = 0: return all io's can I/O on non block
|
53
|
+
# timeout > 0: block when timeout pass miri second or receive events or signals
|
54
|
+
evlist = epoll.wait
|
55
|
+
```
|
56
|
+
|
57
|
+
## Installation
|
58
|
+
|
59
|
+
Add this line to your application's Gemfile:
|
60
|
+
|
61
|
+
gem 'io-epoll'
|
62
|
+
|
63
|
+
And then execute:
|
64
|
+
|
65
|
+
$ bundle
|
66
|
+
|
67
|
+
Or install it yourself as:
|
68
|
+
|
69
|
+
$ gem install io-epoll
|
70
|
+
|
71
|
+
# Fork me !
|
72
|
+
|
73
|
+
This is experimental implementation.
|
74
|
+
I'm waiting for your idea and Pull Request !
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake/extensiontask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
Rake::ExtensionTask.new('epoll') do |ext|
|
6
|
+
ext.name = 'epoll'
|
7
|
+
ext.ext_dir = 'ext/io/epoll'
|
8
|
+
ext.lib_dir = 'lib/io/epoll'
|
9
|
+
end
|
10
|
+
Rake::TestTask.new {|t| t.libs << 'test'}
|
11
|
+
|
@@ -0,0 +1,231 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ruby/io.h"
|
3
|
+
#include "ruby/thread.h"
|
4
|
+
#include <sys/epoll.h>
|
5
|
+
|
6
|
+
VALUE cIO_Epoll;
|
7
|
+
|
8
|
+
struct Epoll {
|
9
|
+
int epfd;
|
10
|
+
int ev_len;
|
11
|
+
};
|
12
|
+
|
13
|
+
static void
|
14
|
+
rb_epoll_free(void *p)
|
15
|
+
{
|
16
|
+
struct Epoll *ptr = p;
|
17
|
+
if (ptr) {
|
18
|
+
if (0 <= ptr->epfd) close(ptr->epfd);
|
19
|
+
ruby_xfree(ptr);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
static size_t
|
24
|
+
rb_epoll_memsize(const void *p)
|
25
|
+
{
|
26
|
+
const struct Epoll *ptr = p;
|
27
|
+
if (!ptr) return 0;
|
28
|
+
return sizeof(struct Epoll);
|
29
|
+
}
|
30
|
+
|
31
|
+
static const rb_data_type_t epoll_data_type = {
|
32
|
+
"epoll",
|
33
|
+
{
|
34
|
+
NULL,
|
35
|
+
rb_epoll_free,
|
36
|
+
rb_epoll_memsize,
|
37
|
+
},
|
38
|
+
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
|
39
|
+
};
|
40
|
+
|
41
|
+
static struct Epoll*
|
42
|
+
get_epoll(VALUE self)
|
43
|
+
{
|
44
|
+
struct Epoll *ptr;
|
45
|
+
rb_check_frozen(self);
|
46
|
+
TypedData_Get_Struct(self, struct Epoll, &epoll_data_type, ptr);
|
47
|
+
if (!ptr) {
|
48
|
+
rb_raise(rb_eIOError, "uninitialized stream");
|
49
|
+
}
|
50
|
+
return ptr;
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE
|
54
|
+
rb_epoll_allocate(VALUE klass)
|
55
|
+
{
|
56
|
+
struct Epoll *ptr;
|
57
|
+
return TypedData_Make_Struct(klass, struct Epoll, &epoll_data_type, ptr);
|
58
|
+
}
|
59
|
+
|
60
|
+
static VALUE
|
61
|
+
rb_epoll_initialize(VALUE self)
|
62
|
+
{
|
63
|
+
struct Epoll *ptr;
|
64
|
+
int epfd;
|
65
|
+
|
66
|
+
TypedData_Get_Struct(self, struct Epoll, &epoll_data_type, ptr);
|
67
|
+
if (ptr->epfd < 0) close(ptr->epfd);
|
68
|
+
epfd = epoll_create(1);
|
69
|
+
if (epfd == -1) {
|
70
|
+
rb_sys_fail("epoll_create was failed");
|
71
|
+
}
|
72
|
+
ptr->epfd = epfd;
|
73
|
+
ptr->ev_len = 0;
|
74
|
+
return self;
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE
|
78
|
+
rb_epoll_fileno(VALUE self)
|
79
|
+
{
|
80
|
+
struct Epoll *ptr = get_epoll(self);
|
81
|
+
return INT2FIX(ptr->epfd);
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE
|
85
|
+
rb_epoll_ctl(int argc, VALUE *argv, VALUE self)
|
86
|
+
{
|
87
|
+
struct Epoll *ptr = get_epoll(self);
|
88
|
+
struct epoll_event ev;
|
89
|
+
VALUE flag;
|
90
|
+
VALUE io;
|
91
|
+
VALUE events;
|
92
|
+
int fd;
|
93
|
+
|
94
|
+
switch (rb_scan_args(argc, argv, "21", &flag, &io, &events)) {
|
95
|
+
case 2:
|
96
|
+
if (FIX2INT(flag) != EPOLL_CTL_DEL) {
|
97
|
+
rb_raise(rb_eArgError, "too few argument for CTL_ADD or CTL_MOD");
|
98
|
+
}
|
99
|
+
break;
|
100
|
+
case 3:
|
101
|
+
if (FIX2INT(flag) != EPOLL_CTL_ADD && FIX2INT(flag) != EPOLL_CTL_MOD) {
|
102
|
+
rb_raise(rb_eArgError, "too many argument for CTL_DEL");
|
103
|
+
}
|
104
|
+
ev.events = FIX2INT(events);
|
105
|
+
ev.data.ptr = (void*)io;
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
|
109
|
+
fd = RFILE(io)->fptr->fd;
|
110
|
+
|
111
|
+
if (epoll_ctl(ptr->epfd, FIX2INT(flag), fd, &ev) == -1) {
|
112
|
+
char buf[128];
|
113
|
+
sprintf(buf, "epoll_ctl() was failed(epfd:%d, fd:%d)", ptr->epfd, fd);
|
114
|
+
rb_sys_fail(buf);
|
115
|
+
}
|
116
|
+
|
117
|
+
switch (FIX2INT(flag)) {
|
118
|
+
case EPOLL_CTL_ADD:
|
119
|
+
ptr->ev_len++;
|
120
|
+
break;
|
121
|
+
case EPOLL_CTL_DEL:
|
122
|
+
ptr->ev_len--;
|
123
|
+
break;
|
124
|
+
case EPOLL_CTL_MOD:
|
125
|
+
break;
|
126
|
+
default:
|
127
|
+
break;
|
128
|
+
}
|
129
|
+
|
130
|
+
return self;
|
131
|
+
}
|
132
|
+
|
133
|
+
struct epoll_wait_args {
|
134
|
+
struct Epoll *ptr;
|
135
|
+
struct epoll_event *evlist;
|
136
|
+
int timeout;
|
137
|
+
};
|
138
|
+
|
139
|
+
static void *
|
140
|
+
rb_epoll_wait_func(void *ptr)
|
141
|
+
{
|
142
|
+
const struct epoll_wait_args *data = ptr;
|
143
|
+
return (void*)(long)epoll_wait(data->ptr->epfd, data->evlist, data->ptr->ev_len, data->timeout);
|
144
|
+
}
|
145
|
+
|
146
|
+
static VALUE
|
147
|
+
rb_epoll_wait(int argc, VALUE *argv, VALUE self)
|
148
|
+
{
|
149
|
+
struct Epoll *ptr = get_epoll(self);
|
150
|
+
VALUE ready_evlist;
|
151
|
+
VALUE event;
|
152
|
+
struct epoll_event *evlist;
|
153
|
+
int i, ready;
|
154
|
+
int timeout = -1;
|
155
|
+
struct epoll_wait_args data;
|
156
|
+
|
157
|
+
if (argc == 1) {
|
158
|
+
timeout = FIX2INT(argv[0]);
|
159
|
+
}
|
160
|
+
evlist = ruby_xmalloc(ptr->ev_len * sizeof(struct epoll_event));
|
161
|
+
|
162
|
+
data.ptr = ptr;
|
163
|
+
data.evlist = evlist;
|
164
|
+
data.timeout = timeout;
|
165
|
+
|
166
|
+
RETRY:
|
167
|
+
ready = (int)(long)rb_thread_call_without_gvl(rb_epoll_wait_func, &data, RUBY_UBF_IO, 0);
|
168
|
+
if (ready == -1) {
|
169
|
+
if (errno == EINTR) {
|
170
|
+
goto RETRY;
|
171
|
+
}
|
172
|
+
else {
|
173
|
+
ruby_xfree(evlist);
|
174
|
+
rb_sys_fail("epoll_wait() was failed");
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
ready_evlist = rb_ary_new_capa(ready);
|
179
|
+
for (i = 0; i < ready; i++) {
|
180
|
+
event = rb_obj_alloc(rb_path2class("IO::Epoll::Event"));
|
181
|
+
RSTRUCT_SET(event, 0, (VALUE) evlist[i].data.ptr);
|
182
|
+
RSTRUCT_SET(event, 1, INT2FIX(evlist[i].events));
|
183
|
+
rb_ary_store(ready_evlist, i, event);
|
184
|
+
}
|
185
|
+
ruby_xfree(evlist);
|
186
|
+
return ready_evlist;
|
187
|
+
}
|
188
|
+
|
189
|
+
static VALUE
|
190
|
+
rb_epoll_close(VALUE self)
|
191
|
+
{
|
192
|
+
struct Epoll *ptr = get_epoll(self);
|
193
|
+
if (close(ptr->epfd) == -1) {
|
194
|
+
rb_raise(rb_eIOError, "file descriptor duplicate close %ld", INT2FIX(ptr->epfd));
|
195
|
+
}
|
196
|
+
ptr->epfd = -1;
|
197
|
+
return Qnil;
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
rb_epoll_length(VALUE self)
|
202
|
+
{
|
203
|
+
struct Epoll *ptr = get_epoll(self);
|
204
|
+
return INT2FIX(ptr->ev_len);
|
205
|
+
}
|
206
|
+
|
207
|
+
void
|
208
|
+
Init_epoll()
|
209
|
+
{
|
210
|
+
cIO_Epoll = rb_define_class_under(rb_cIO, "Epoll", rb_cObject);
|
211
|
+
rb_define_alloc_func(cIO_Epoll, rb_epoll_allocate);
|
212
|
+
|
213
|
+
rb_define_method(cIO_Epoll, "initialize", rb_epoll_initialize, 0);
|
214
|
+
rb_define_method(cIO_Epoll, "fileno", rb_epoll_fileno, 0);
|
215
|
+
rb_define_method(cIO_Epoll, "ctl", rb_epoll_ctl, -1);
|
216
|
+
rb_define_method(cIO_Epoll, "wait", rb_epoll_wait, -1);
|
217
|
+
rb_define_method(cIO_Epoll, "close", rb_epoll_close, 0);
|
218
|
+
rb_define_method(cIO_Epoll, "length", rb_epoll_length, 0);
|
219
|
+
rb_define_alias(cIO_Epoll, "size", "length");
|
220
|
+
rb_define_const(cIO_Epoll, "IN", INT2FIX(EPOLLIN));
|
221
|
+
rb_define_const(cIO_Epoll, "PRI", INT2FIX(EPOLLPRI));
|
222
|
+
rb_define_const(cIO_Epoll, "RDHUP", INT2FIX(EPOLLRDHUP));
|
223
|
+
rb_define_const(cIO_Epoll, "OUT", INT2FIX(EPOLLOUT));
|
224
|
+
rb_define_const(cIO_Epoll, "ET", INT2FIX(EPOLLET));
|
225
|
+
rb_define_const(cIO_Epoll, "ONESHOT", INT2FIX(EPOLLONESHOT));
|
226
|
+
rb_define_const(cIO_Epoll, "ERR", INT2FIX(EPOLLERR));
|
227
|
+
rb_define_const(cIO_Epoll, "HUP", INT2FIX(EPOLLHUP));
|
228
|
+
rb_define_const(cIO_Epoll, "CTL_ADD", INT2FIX(EPOLL_CTL_ADD));
|
229
|
+
rb_define_const(cIO_Epoll, "CTL_MOD", INT2FIX(EPOLL_CTL_MOD));
|
230
|
+
rb_define_const(cIO_Epoll, "CTL_DEL", INT2FIX(EPOLL_CTL_DEL));
|
231
|
+
}
|
data/io-epoll.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "io-epoll"
|
3
|
+
spec.version = "0.0.1"
|
4
|
+
spec.authors = ["ksss"]
|
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)}
|
8
|
+
spec.homepage = ""
|
9
|
+
spec.license = "MIT"
|
10
|
+
|
11
|
+
spec.files = `git ls-files`.split($/)
|
12
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
spec.extensions = ["ext/io/epoll/extconf.rb"]
|
16
|
+
|
17
|
+
spec.add_development_dependency "bundler"
|
18
|
+
spec.add_development_dependency "rake"
|
19
|
+
spec.add_development_dependency 'rake-compiler'
|
20
|
+
spec.add_development_dependency 'test-unit'
|
21
|
+
end
|
data/lib/io/epoll.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'io/epoll/epoll'
|
2
|
+
|
3
|
+
class IO
|
4
|
+
class Epoll
|
5
|
+
class Event < Struct.new(:data, :events)
|
6
|
+
end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
alias create new
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(io, events)
|
13
|
+
ctl(CTL_ADD, io, events)
|
14
|
+
end
|
15
|
+
|
16
|
+
def mod(io, events)
|
17
|
+
ctl(CTL_MOD, io, events)
|
18
|
+
end
|
19
|
+
|
20
|
+
def del(io)
|
21
|
+
ctl(CTL_DEL, io)
|
22
|
+
end
|
23
|
+
|
24
|
+
def closed?
|
25
|
+
fileno < 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.epoll(ios, events)
|
30
|
+
open_len = ios.length
|
31
|
+
ep = Epoll.create
|
32
|
+
ios.each do |io|
|
33
|
+
ep.add(io, events)
|
34
|
+
end
|
35
|
+
if block_given?
|
36
|
+
while 0 < open_len
|
37
|
+
evlist = ep.wait
|
38
|
+
evlist.each do |ev|
|
39
|
+
yield ev
|
40
|
+
if ev.events & (Epoll::HUP|Epoll::ERR)
|
41
|
+
open_len -= 1
|
42
|
+
ev.data.close
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
ep.wait
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/test/test_epoll.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'timeout'
|
3
|
+
require_relative '../lib/io/epoll'
|
4
|
+
|
5
|
+
class TestIOEpoll < Test::Unit::TestCase
|
6
|
+
def test_initalize
|
7
|
+
assert_instance_of(IO::Epoll, IO::Epoll.new);
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_fileno
|
11
|
+
assert { 0 < IO::Epoll.new.fileno }
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_ctl
|
15
|
+
ep = IO::Epoll.new
|
16
|
+
io = IO.new(1, 'w')
|
17
|
+
assert_raise(ArgumentError) { ep.ctl }
|
18
|
+
assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD) }
|
19
|
+
assert_raise(ArgumentError) { ep.ctl(IO::Epoll::CTL_ADD, io) }
|
20
|
+
assert { ep == ep.ctl(IO::Epoll::CTL_ADD, io , IO::Epoll::OUT) }
|
21
|
+
assert_raise(ArgumentError) { ep.ctl(-1, io) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_add
|
25
|
+
ep = IO::Epoll.new
|
26
|
+
io = IO.new(1, 'w')
|
27
|
+
assert { ep == ep.add(io, IO::Epoll::OUT) }
|
28
|
+
ep.close
|
29
|
+
assert_raise(Errno::EBADF) { ep.add(io, IO::Epoll::OUT) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_mod
|
33
|
+
ep = IO::Epoll.new
|
34
|
+
io = IO.new(1, 'w')
|
35
|
+
assert_raise(Errno::ENOENT) { ep.mod(io, IO::Epoll::IN) }
|
36
|
+
ep == ep.add(io, IO::Epoll::OUT)
|
37
|
+
assert { ep == ep.mod(io, IO::Epoll::IN) }
|
38
|
+
ep.close
|
39
|
+
assert_raise(Errno::EBADF) { ep.add(io, IO::Epoll::OUT) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_del
|
43
|
+
ep = IO::Epoll.new
|
44
|
+
io = IO.new(1, 'w')
|
45
|
+
assert_raise(Errno::ENOENT) { ep.del(io) }
|
46
|
+
ep.add(io, IO::Epoll::OUT)
|
47
|
+
assert { ep == ep.del(io) }
|
48
|
+
ep.close
|
49
|
+
assert_raise(Errno::EBADF) { ep.del(io) }
|
50
|
+
end
|
51
|
+
|
52
|
+
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 }
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_wait_with_timeout
|
61
|
+
ep = IO::Epoll.new
|
62
|
+
io = IO.new(1, 'w')
|
63
|
+
ep.add(io, IO::Epoll::IN)
|
64
|
+
assert { [] == ep.wait(0) }
|
65
|
+
assert { [] == ep.wait(1) }
|
66
|
+
assert_raise(TimeoutError) do
|
67
|
+
timeout(0.01) { ep.wait(-1) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_size
|
72
|
+
ep = IO::Epoll.new
|
73
|
+
io = IO.new(0, 'r')
|
74
|
+
ep.add(io, IO::Epoll::IN)
|
75
|
+
assert { 1 == ep.size }
|
76
|
+
ep.del(io)
|
77
|
+
assert { 0 == ep.size }
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_close_closed?
|
81
|
+
ep = IO::Epoll.new
|
82
|
+
assert { false == ep.closed? }
|
83
|
+
assert { nil == ep.close }
|
84
|
+
assert_raise(IOError){ ep.close }
|
85
|
+
assert { true == ep.closed? }
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_epoll
|
89
|
+
r, w = IO.pipe
|
90
|
+
fork {
|
91
|
+
r.close
|
92
|
+
w.write('ok')
|
93
|
+
}
|
94
|
+
w.close
|
95
|
+
ret = []
|
96
|
+
evs = IO.epoll([r], IO::Epoll::IN)
|
97
|
+
assert { 'ok' == evs[0].data.read }
|
98
|
+
assert { false == evs[0].data.closed? }
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_epoll_with_block
|
102
|
+
r, w = IO.pipe
|
103
|
+
fork {
|
104
|
+
r.close
|
105
|
+
w.write('ok')
|
106
|
+
}
|
107
|
+
w.close
|
108
|
+
ret = []
|
109
|
+
IO.epoll([r], IO::Epoll::IN) do |ev|
|
110
|
+
ret << ev
|
111
|
+
assert { 'ok' == ev.data.read }
|
112
|
+
end
|
113
|
+
assert { true == ret[0].data.closed? }
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_thread
|
117
|
+
ep = IO::Epoll.new
|
118
|
+
io = IO.new(1, 'w')
|
119
|
+
ep.add(io, IO::Epoll::OUT)
|
120
|
+
ret = nil
|
121
|
+
Thread.start {
|
122
|
+
ret = ep.wait
|
123
|
+
}.join
|
124
|
+
assert { io == ret[0].data }
|
125
|
+
end
|
126
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: io-epoll
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ksss
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: test-unit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: An experimental binding of epoll(7)
|
70
|
+
email:
|
71
|
+
- co000ri@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions:
|
74
|
+
- ext/io/epoll/extconf.rb
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- ext/io/epoll/epoll.c
|
84
|
+
- ext/io/epoll/extconf.rb
|
85
|
+
- io-epoll.gemspec
|
86
|
+
- lib/io/epoll.rb
|
87
|
+
- test/test_epoll.rb
|
88
|
+
homepage: ''
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 2.4.1
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: An experimental binding of epoll(7)
|
112
|
+
test_files:
|
113
|
+
- test/test_epoll.rb
|