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 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
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ *.rbc
3
+ *.bundle
4
+ *.so
5
+ *.o
6
+ tmp
7
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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
+ }
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ if !have_header("sys/epoll.h")
4
+ puts "*** err: <sys/epoll.h> header must be installed ***"
5
+ exit 1
6
+ end
7
+ create_makefile('io/epoll/epoll')
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
@@ -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