io-epoll 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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