evt 0.1.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 666a665e9a03c15a364613ceac651e6e71becfa51b780b81d6cb56652ad6489b
4
- data.tar.gz: 0c21649125a1d4f6c4002b8d8da2e235d98763cde42bc8ae2f0aaac3353a98f5
3
+ metadata.gz: f49f37d3240b1878b00acaeea453e00c9dae2a96c8c7f12889836d653d6b1835
4
+ data.tar.gz: 2af4b0238768dcb2b4112eaff379cad3899633eab69017517f36d5d51ba1fae7
5
5
  SHA512:
6
- metadata.gz: 3b6fe6c7ee071b3da47e4ba66d581d18a1e1e3df3a34e072588cdd1d2b1a0816d1b85ebf6fe89190fefee6c0bc2d8d8df9b30031625febbe02062bb6db366c58
7
- data.tar.gz: d42b01b897e8d673060a5ed5ff5ffee6156cb63b3ad2e7e777044fa674e1ac59e53fc60167231745512cbfe1b31c4fc51b74d2a5331876ea63d8984fbe3311f8
6
+ metadata.gz: 58222d04ff91f47667697fd63d6d235d85c8204e09a82ac18dbd05b27d37eb79d6bcda034117684e2d49cd0cd67d2818df5264a4f73751851f1ebefdbe3a9de2
7
+ data.tar.gz: 17c54e28beb805e30a3883446a807c5114287ba3c37b402a85dcba013f2910e8aca7d29c17efe527dd050a971f224ff0e8f4f2aacd36ef8cbe7970ff8aa06d56
@@ -0,0 +1,21 @@
1
+ name: Build
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches:
6
+ - master
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-20.04
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+ - uses: ruby/setup-ruby@master
13
+ with:
14
+ ruby-version: '3.0'
15
+ bundler-cache: false
16
+ - name: Install Dependencies
17
+ run: |
18
+ gem install bundler
19
+ bundle install --jobs 4 --retry 3
20
+ - name: Build
21
+ run: rake build
@@ -0,0 +1,40 @@
1
+ name: CI Tests
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches:
6
+ - master
7
+ schedule:
8
+ - cron: '0 7 * * SUN'
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ include:
15
+ - { os: ubuntu-20.04, ruby: '3.0', backend: epoll }
16
+ - { os: ubuntu-20.04, ruby: '3.0', backend: ruby, disable-epoll: 1 }
17
+ - { os: macos-11.0, ruby: '3.0', backend: kqueue }
18
+ - { os: macos-11.0, ruby: '3.0', backend: ruby, disable-kqueue: 1 }
19
+ - { os: windows-2019, ruby: mingw, backend: ruby }
20
+ - { os: windows-2019, ruby: mswin, backend: ruby }
21
+ name: test ${{ matrix.os }} ${{ matrix.ruby }} ${{ matrix.backend }}
22
+ runs-on: ${{ matrix.os }}
23
+ timeout-minutes: 5
24
+ steps:
25
+ - uses: actions/checkout@v2
26
+ - uses: ruby/setup-ruby@master
27
+ with:
28
+ ruby-version: ${{ matrix.ruby }}
29
+ bundler-cache: false
30
+ - name: Install Dependencies
31
+ run: |
32
+ gem install bundler
33
+ bundle install --jobs 4 --retry 3
34
+ - name: Compile
35
+ env:
36
+ DISABLE_EPOLL: ${{ matrix.disable-epoll }}
37
+ DISABLE_KQUEUE: ${{ matrix.disable-kqueue }}
38
+ run: rake compile
39
+ - name: Test
40
+ run: rake test
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
  /*.gem
10
10
  /lib/*.bundle
11
11
  /lib/*.so
12
+ Gemfile.lock
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in evt.gemspec
4
4
  gemspec
5
5
 
6
- gem "rake", "~> 12.0"
6
+ gem "rake", "~> 13.0"
7
7
  gem "minitest", "~> 5.0"
data/README.md CHANGED
@@ -1,10 +1,47 @@
1
- # evt
1
+ # Evt
2
2
 
3
- [![Build Status](https://travis-ci.org/dsh0416/evt.svg?branch=master)](https://travis-ci.org/dsh0416/evt)
3
+ The Event Library that designed for Ruby 3.0 Fiber Scheduler.
4
4
 
5
- A Handcrafted Low-Level Event Handler designed as Ruby 3 Scheduler.
5
+ **This gem is still under development, APIs and features are not stable. Advices and PRs are highly welcome.**
6
6
 
7
- Supports `epoll`, `kqueue`, IOCP (WIP), and Ruby `select` fallback.
7
+ [![CI Tests](https://github.com/dsh0416/evt/workflows/CI%20Tests/badge.svg)](https://github.com/dsh0416/evt/actions?query=workflow%3A%22Build%22)
8
+ [![Build](https://github.com/dsh0416/evt/workflows/Build/badge.svg)](https://github.com/dsh0416/evt/actions?query=workflow%3A%22CI+Tests%22)
9
+ [![Gem Version](https://badge.fury.io/rb/evt.svg)](https://rubygems.org/gems/evt)
10
+ [![Downloads](https://ruby-gem-downloads-badge.herokuapp.com/evt?type=total)](https://rubygems.org/gems/evt)
11
+
12
+ ## Features
13
+
14
+ ### IO Backend Support
15
+
16
+ | | Linux | Windows | macOS | FreeBSD |
17
+ | --------------- | ----------- | ------------| ----------- | ----------- |
18
+ | io_uring | ✅ (See 1) | ❌ | ❌ | ❌ |
19
+ | epoll | ✅ (See 2) | ❌ | ❌ | ❌ |
20
+ | kqueue | ❌ | ❌ | ✅ (⚠️ See 5) | ✅ |
21
+ | IOCP | ❌ | ❌ (⚠️See 3) | ❌ | ❌ |
22
+ | Ruby (`IO.select`) | ✅ Fallback | ✅ (⚠️See 4) | ✅ Fallback | ✅ Fallback |
23
+
24
+ 1. when liburing is installed
25
+ 2. when kernel version >= 2.6.8
26
+ 3. WOULD NOT WORK until `FILE_FLAG_OVERLAPPED` is included in I/O initialization process.
27
+ 4. Some I/Os are not able to be nonblock under Windows. See [Scheduler Docs](https://docs.ruby-lang.org/en/master/doc/scheduler_md.html#label-IO).
28
+ 5. `kqueue` performance in Darwin is very poor. **MAY BE DISABLED IN THE FUTURE.**
29
+
30
+ ### Benchmark
31
+
32
+ The benchmark is running under `v0.2.2` version. See [evt-server-benchmark](https://github.com/dsh0416/evt-server-benchmark) for test code, the test is running under a single-thread server.
33
+
34
+ The test command is `wrk -t4 -c8192 -d30s http://localhost:3001`.
35
+
36
+ All of the systems have set their file descriptor limit to maximum.
37
+
38
+ | OS | CPU | Memory | Backend | req/s |
39
+ | ----- | ----------- | ------ | ---------------------- | -------- |
40
+ | Linux | Ryzen 2700x | 64GB | epoll | 54680.08 |
41
+ | Linux | Ryzen 2700x | 64GB | io_uring | 50245.53 |
42
+ | Linux | Ryzen 2700x | 64GB | IO.select (using poll) | 44159.23 |
43
+ | macOS | i7-6820HQ | 16GB | kqueue | 37855.53 |
44
+ | macOS | i7-6820HQ | 16GB | IO.select (using poll) | 28293.36 |
8
45
 
9
46
  ## Install
10
47
 
@@ -18,17 +55,33 @@ gem install evt
18
55
  require 'evt'
19
56
 
20
57
  rd, wr = IO.pipe
21
- Thread.current.scheduler = Evt::Scheduler.new
58
+ scheduler = Evt::Scheduler.new
59
+
60
+ Fiber.set_scheduler scheduler
22
61
 
23
- hit = 0
24
- fiber = Fiber.new do
25
- scheduler.wait_readable(rd)
26
- hit += 1
62
+ Fiber.schedule do
63
+ message = rd.read(20)
64
+ puts message
65
+ rd.close
27
66
  end
28
67
 
29
- wr.write('Hello World')
30
- fiber.resume
31
- Thread.current.scheduler.run
68
+ Fiber.schedule do
69
+ wr.write("Hello World")
70
+ wr.close
71
+ end
32
72
 
33
- puts hit # => 1
73
+ # "Hello World"
34
74
  ```
75
+
76
+ ## Roadmap
77
+
78
+ - [x] Support epoll/kqueue/select
79
+ - [x] Upgrade to the latest Scheduler API
80
+ - [x] Support io_uring
81
+ - [x] Support iov features of io_uring
82
+ - [x] Support IOCP (**NOT ENABLED YET**)
83
+ - [x] Setup tests with Ruby 3
84
+ - [x] Selectable backend compilation by environment variable
85
+ - [ ] Support IOCP with iov features
86
+ - [ ] Setup more tests for production purpose
87
+ - [ ] Documentation for usages
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ Rake::TestTask.new(:test) do |t|
11
11
  t.libs << "test"
12
12
  t.libs << "lib"
13
13
  t.test_files = FileList["test/**/*_test.rb"]
14
+ t.verbose = true
14
15
  end
15
16
 
16
17
  task :default => :test
@@ -6,11 +6,11 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ["Delton Ding"]
7
7
  spec.email = ["dsh0416@gmail.com"]
8
8
 
9
- spec.summary = "A low-level Event Handler designed for Ruby 3 Scheduler"
9
+ spec.summary = "The Event Library that designed for Ruby 3.0 Fiber Scheluer."
10
10
  spec.description = "A low-level Event Handler designed for Ruby 3 Scheduler for better performance"
11
11
  spec.homepage = "https://github.com/dsh0416/evt"
12
12
  spec.license = 'BSD-3-Clause'
13
- spec.required_ruby_version = '>= 2.7.1'
13
+ spec.required_ruby_version = '>= 3.0.0.rc1'
14
14
 
15
15
  spec.metadata["homepage_uri"] = spec.homepage
16
16
  spec.metadata["source_code_uri"] = "https://github.com/dsh0416/evt"
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec|
18
18
  # Specify which files should be added to the gem when it is released.
19
19
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
20
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|examples|.vscode)/}) }
22
22
  end
23
23
  spec.require_paths = ["lib"]
24
24
  spec.extensions = ['ext/evt/extconf.rb']
25
25
 
26
26
  spec.add_development_dependency 'rake-compiler', '~> 1.0'
27
+ spec.add_development_dependency 'simplecov', '~> 0.20.0'
27
28
  end
@@ -0,0 +1,89 @@
1
+ #ifndef EPOLL_H
2
+ #define EPOLL_H
3
+ #include "evt.h"
4
+
5
+ #if HAVE_SYS_EPOLL_H
6
+ VALUE method_scheduler_epoll_init(VALUE self) {
7
+ rb_iv_set(self, "@epfd", INT2NUM(epoll_create(1))); // Size of epoll is ignored after Linux 2.6.8.
8
+ return Qnil;
9
+ }
10
+
11
+ VALUE method_scheduler_epoll_register(VALUE self, VALUE io, VALUE interest) {
12
+ struct epoll_event event;
13
+ ID id_fileno = rb_intern("fileno");
14
+ int epfd = NUM2INT(rb_iv_get(self, "@epfd"));
15
+ int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
16
+ int ruby_interest = NUM2INT(interest);
17
+ int readable = NUM2INT(rb_const_get(rb_cIO, rb_intern("READABLE")));
18
+ int writable = NUM2INT(rb_const_get(rb_cIO, rb_intern("WRITABLE")));
19
+
20
+ if (ruby_interest & readable) {
21
+ event.events |= EPOLLIN;
22
+ }
23
+
24
+ if (ruby_interest & writable) {
25
+ event.events |= EPOLLOUT;
26
+ }
27
+
28
+ event.data.ptr = (void*) io;
29
+
30
+ epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
31
+ return Qnil;
32
+ }
33
+
34
+ VALUE method_scheduler_epoll_deregister(VALUE self, VALUE io) {
35
+ ID id_fileno = rb_intern("fileno");
36
+ int epfd = NUM2INT(rb_iv_get(self, "@epfd"));
37
+ int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
38
+ epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); // Require Linux 2.6.9 for NULL event.
39
+ return Qnil;
40
+ }
41
+
42
+ VALUE method_scheduler_epoll_wait(VALUE self) {
43
+ int n, epfd, i, event_flag, timeout;
44
+ VALUE next_timeout, obj_io, readables, writables, result;
45
+ ID id_next_timeout = rb_intern("next_timeout");
46
+ ID id_push = rb_intern("push");
47
+
48
+ epfd = NUM2INT(rb_iv_get(self, "@epfd"));
49
+ next_timeout = rb_funcall(self, id_next_timeout, 0);
50
+ readables = rb_ary_new();
51
+ writables = rb_ary_new();
52
+
53
+ if (next_timeout == Qnil) {
54
+ timeout = -1;
55
+ } else {
56
+ timeout = NUM2INT(next_timeout);
57
+ }
58
+
59
+ struct epoll_event events[EPOLL_MAX_EVENTS];
60
+
61
+ n = epoll_wait(epfd, events, EPOLL_MAX_EVENTS, timeout);
62
+ if (n < 0) {
63
+ rb_raise(rb_eIOError, "unable to call epoll_wait");
64
+ }
65
+
66
+ for (i = 0; i < n; i++) {
67
+ event_flag = events[i].events;
68
+ if (event_flag & EPOLLIN) {
69
+ obj_io = (VALUE) events[i].data.ptr;
70
+ rb_funcall(readables, id_push, 1, obj_io);
71
+ }
72
+
73
+ if (event_flag & EPOLLOUT) {
74
+ obj_io = (VALUE) events[i].data.ptr;
75
+ rb_funcall(writables, id_push, 1, obj_io);
76
+ }
77
+ }
78
+
79
+ result = rb_ary_new2(2);
80
+ rb_ary_store(result, 0, readables);
81
+ rb_ary_store(result, 1, writables);
82
+ return result;
83
+ }
84
+
85
+ VALUE method_scheduler_epoll_backend(VALUE klass) {
86
+ return rb_str_new_cstr("epoll");
87
+ }
88
+ #endif
89
+ #endif
@@ -1,218 +1,45 @@
1
+ #ifndef EVT_C
2
+ #define EVT_C
3
+
1
4
  #include "evt.h"
2
5
 
3
6
  void Init_evt_ext()
4
7
  {
8
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
9
+ rb_ext_ractor_safe(true);
10
+ #endif
5
11
  Evt = rb_define_module("Evt");
6
- Scheduler = rb_define_class_under(Evt, "Scheduler", rb_cObject);
7
- rb_define_singleton_method(Scheduler, "backend", method_scheduler_backend, 0);
8
- rb_define_method(Scheduler, "init_selector", method_scheduler_init, 0);
9
- rb_define_method(Scheduler, "register", method_scheduler_register, 2);
10
- rb_define_method(Scheduler, "deregister", method_scheduler_deregister, 1);
11
- rb_define_method(Scheduler, "wait", method_scheduler_wait, 0);
12
- }
13
-
14
-
15
- #if defined(__linux__) // TODO: Do more checks for using epoll
16
- #include <sys/epoll.h>
17
- #define EPOLL_MAX_EVENTS 64
18
-
19
- VALUE method_scheduler_init(VALUE self) {
20
- rb_iv_set(self, "@epfd", INT2NUM(epoll_create(1))); // Size of epoll is ignored after Linux 2.6.8.
21
- return Qnil;
22
- }
23
-
24
- VALUE method_scheduler_register(VALUE self, VALUE io, VALUE interest) {
25
- struct epoll_event event;
26
- ID id_fileno = rb_intern("fileno");
27
- int epfd = NUM2INT(rb_iv_get(self, "@epfd"));
28
- int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
29
- int ruby_interest = NUM2INT(interest);
30
- int readable = NUM2INT(rb_const_get(rb_cIO, rb_intern("WAIT_READABLE")));
31
- int writable = NUM2INT(rb_const_get(rb_cIO, rb_intern("WAIT_WRITABLE")));
32
-
33
- if (ruby_interest & readable) {
34
- event.events |= EPOLLIN;
35
- } else if (ruby_interest & writable) {
36
- event.events |= EPOLLOUT;
37
- }
38
- event.data.ptr = (void*) io;
39
-
40
- epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
41
- return Qnil;
42
- }
43
-
44
- VALUE method_scheduler_deregister(VALUE self, VALUE io) {
45
- ID id_fileno = rb_intern("fileno");
46
- int epfd = NUM2INT(rb_iv_get(self, "@epfd"));
47
- int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
48
- epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); // Require Linux 2.6.9 for NULL event.
49
- return Qnil;
50
- }
51
-
52
- VALUE method_scheduler_wait(VALUE self) {
53
- int n, epfd, i, event_flag, timeout;
54
- VALUE next_timeout, obj_io, readables, writables, result;
55
- ID id_next_timeout = rb_intern("next_timeout");
56
- ID id_push = rb_intern("push");
57
-
58
- epfd = NUM2INT(rb_iv_get(self, "@epfd"));
59
- next_timeout = rb_funcall(self, id_next_timeout, 0);
60
- readables = rb_ary_new();
61
- writables = rb_ary_new();
62
-
63
- if (next_timeout == Qnil) {
64
- timeout = -1;
65
- } else {
66
- timeout = NUM2INT(next_timeout);
67
- }
68
-
69
- struct epoll_event* events = (struct epoll_event*) xmalloc(sizeof(struct epoll_event) * EPOLL_MAX_EVENTS);
70
-
71
- n = epoll_wait(epfd, events, EPOLL_MAX_EVENTS, timeout);
72
- // TODO: Check if n >= 0
73
-
74
- for (i = 0; i < n; i++) {
75
- event_flag = events[i].events;
76
- if (event_flag & EPOLLIN) {
77
- obj_io = (VALUE) events[i].data.ptr;
78
- rb_funcall(readables, id_push, 1, obj_io);
79
- } else if (event_flag & EPOLLOUT) {
80
- obj_io = (VALUE) events[i].data.ptr;
81
- rb_funcall(writables, id_push, 1, obj_io);
82
- }
83
- }
84
-
85
- result = rb_ary_new2(2);
86
- rb_ary_store(result, 0, readables);
87
- rb_ary_store(result, 1, writables);
88
-
89
- xfree(events);
90
- return result;
91
- }
92
-
93
- VALUE method_scheduler_backend() {
94
- return rb_str_new_cstr("epoll");
95
- }
96
- #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
97
- #include <sys/event.h>
98
- #define KQUEUE_MAX_EVENTS 64
99
-
100
- VALUE method_scheduler_init(VALUE self) {
101
- rb_iv_set(self, "@kq", INT2NUM(kqueue()));
102
- return Qnil;
103
- }
104
-
105
- VALUE method_scheduler_register(VALUE self, VALUE io, VALUE interest) {
106
- struct kevent event;
107
- u_short event_flags = 0;
108
- ID id_fileno = rb_intern("fileno");
109
- int kq = NUM2INT(rb_iv_get(self, "@kq"));
110
- int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
111
- int ruby_interest = NUM2INT(interest);
112
- int readable = NUM2INT(rb_const_get(rb_cIO, rb_intern("WAIT_READABLE")));
113
- int writable = NUM2INT(rb_const_get(rb_cIO, rb_intern("WAIT_WRITABLE")));
114
-
115
- if (ruby_interest & readable) {
116
- event_flags |= EVFILT_READ;
117
- } else if (ruby_interest & writable) {
118
- event_flags |= EVFILT_WRITE;
119
- }
120
-
121
- EV_SET(&event, fd, event_flags, EV_ADD|EV_ENABLE, 0, 0, (void*) io);
122
- kevent(kq, &event, 1, NULL, 0, NULL); // TODO: Check the return value
123
- return Qnil;
124
- }
125
-
126
- VALUE method_scheduler_deregister(VALUE self, VALUE io) {
127
- struct kevent event;
128
- ID id_fileno = rb_intern("fileno");
129
- int kq = NUM2INT(rb_iv_get(self, "@kq"));
130
- int fd = NUM2INT(rb_funcall(io, id_fileno, 0));
131
- EV_SET(&event, fd, 0, EV_DELETE, 0, 0, NULL);
132
- kevent(kq, &event, 1, NULL, 0, NULL); // TODO: Check the return value
133
- return Qnil;
134
- }
135
-
136
- VALUE method_scheduler_wait(VALUE self) {
137
- int n, kq, i;
138
- u_short event_flags = 0;
139
-
140
- struct kevent* events; // Event Triggered
141
- struct timespec timeout;
142
- VALUE next_timeout, obj_io, readables, writables, result;
143
- ID id_next_timeout = rb_intern("next_timeout");
144
- ID id_push = rb_intern("push");
145
-
146
- kq = NUM2INT(rb_iv_get(self, "@kq"));
147
- next_timeout = rb_funcall(self, id_next_timeout, 0);
148
- readables = rb_ary_new();
149
- writables = rb_ary_new();
150
-
151
- events = (struct kevent*) xmalloc(sizeof(struct kevent) * KQUEUE_MAX_EVENTS);
152
-
153
- if (next_timeout == Qnil || NUM2INT(next_timeout) == -1) {
154
- n = kevent(kq, NULL, 0, events, KQUEUE_MAX_EVENTS, NULL);
155
- } else {
156
- timeout.tv_sec = next_timeout / 1000;
157
- timeout.tv_nsec = next_timeout % 1000 * 1000 * 1000;
158
- n = kevent(kq, NULL, 0, events, KQUEUE_MAX_EVENTS, &timeout);
159
- }
160
-
161
- // TODO: Check if n >= 0
162
- for (i = 0; i < n; i++) {
163
- event_flags = events[i].filter;
164
- if (event_flags & EVFILT_READ) {
165
- obj_io = (VALUE) events[i].udata;
166
- rb_funcall(readables, id_push, 1, obj_io);
167
- } else if (event_flags & EVFILT_WRITE) {
168
- obj_io = (VALUE) events[i].udata;
169
- rb_funcall(writables, id_push, 1, obj_io);
170
- }
171
- }
172
-
173
- result = rb_ary_new2(2);
174
- rb_ary_store(result, 0, readables);
175
- rb_ary_store(result, 1, writables);
176
-
177
- xfree(events);
178
- return result;
179
- }
180
-
181
- VALUE method_scheduler_backend() {
182
- return rb_str_new_cstr("kqueue");
183
- }
184
- #else
185
- // Fallback to IO.select
186
- VALUE method_scheduler_init(VALUE self) {
187
- return Qnil;
188
- }
189
-
190
- VALUE method_scheduler_register(VALUE self, VALUE io, VALUE interest) {
191
- return Qnil;
192
- }
193
-
194
- VALUE method_scheduler_deregister(VALUE self, VALUE io) {
195
- return Qnil;
196
- }
197
-
198
- VALUE method_scheduler_wait(VALUE self) {
199
- // return IO.select(@readable.keys, @writable.keys, [], next_timeout)
200
- VALUE readable, writable, readable_keys, writable_keys, next_timeout;
201
- ID id_select = rb_intern("select");
202
- ID id_keys = rb_intern("keys");
203
- ID id_next_timeout = rb_intern("next_timeout");
204
-
205
- readable = rb_iv_get(self, "@readable");
206
- writable = rb_iv_get(self, "@writable");
207
-
208
- readable_keys = rb_funcall(readable, id_keys, 0);
209
- writable_keys = rb_funcall(writable, id_keys, 0);
210
- next_timeout = rb_funcall(self, id_next_timeout, 0);
211
-
212
- return rb_funcall(rb_cIO, id_select, 4, readable_keys, writable_keys, rb_ary_new(), next_timeout);
213
- }
214
-
215
- VALUE method_scheduler_backend() {
216
- return rb_str_new_cstr("ruby");
217
- }
218
- #endif
12
+ Bundled = rb_define_class_under(Evt, "Bundled", rb_cObject);
13
+ Payload = rb_define_class_under(Bundled, "Payload", rb_cObject);
14
+ Fiber = rb_define_class("Fiber", rb_cObject);
15
+ #if HAVE_LIBURING_H
16
+ rb_define_singleton_method(Bundled, "uring_backend", method_scheduler_uring_backend, 0);
17
+ rb_define_method(Bundled, "uring_init_selector", method_scheduler_uring_init, 0);
18
+ rb_define_method(Bundled, "uring_register", method_scheduler_uring_register, 2);
19
+ rb_define_method(Bundled, "uring_wait", method_scheduler_uring_wait, 0);
20
+ rb_define_method(Bundled, "uring_io_read", method_scheduler_uring_io_read, 4);
21
+ rb_define_method(Bundled, "uring_io_write", method_scheduler_uring_io_write, 4);
22
+ #endif
23
+ #if HAVE_SYS_EPOLL_H
24
+ rb_define_singleton_method(Bundled, "epoll_backend", method_scheduler_epoll_backend, 0);
25
+ rb_define_method(Bundled, "epoll_init_selector", method_scheduler_epoll_init, 0);
26
+ rb_define_method(Bundled, "epoll_register", method_scheduler_epoll_register, 2);
27
+ rb_define_method(Bundled, "epoll_deregister", method_scheduler_epoll_deregister, 1);
28
+ rb_define_method(Bundled, "epoll_wait", method_scheduler_epoll_wait, 0);
29
+ #endif
30
+ #if HAVE_SYS_EVENT_H
31
+ rb_define_singleton_method(Bundled, "kqueue_backend", method_scheduler_kqueue_backend, 0);
32
+ rb_define_method(Bundled, "kqueue_init_selector", method_scheduler_kqueue_init, 0);
33
+ rb_define_method(Bundled, "kqueue_register", method_scheduler_kqueue_register, 2);
34
+ rb_define_method(Bundled, "kqueue_wait", method_scheduler_kqueue_wait, 0);
35
+ #endif
36
+ rb_define_singleton_method(Bundled, "select_backend", method_scheduler_select_backend, 0);
37
+ rb_define_method(Bundled, "select_wait", method_scheduler_select_wait, 0);
38
+ }
39
+
40
+ #include "uring.h"
41
+ #include "epoll.h"
42
+ #include "kqueue.h"
43
+ // #include "iocp.h"
44
+ #include "select.h"
45
+ #endif