evt 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +51 -0
- data/.gitignore +1 -0
- data/Gemfile +1 -1
- data/README.md +50 -13
- data/evt.gemspec +2 -2
- data/ext/evt/epoll.h +91 -0
- data/ext/evt/evt.c +22 -206
- data/ext/evt/evt.h +72 -1
- data/ext/evt/extconf.rb +9 -2
- data/ext/evt/iocp.h +126 -0
- data/ext/evt/kqueue.h +97 -0
- data/ext/evt/select.h +36 -0
- data/ext/evt/uring.h +201 -0
- data/lib/evt.rb +1 -2
- data/lib/evt/scheduler.rb +51 -92
- data/lib/evt/version.rb +1 -1
- metadata +10 -7
- data/.travis.yml +0 -25
- data/Gemfile.lock +0 -24
- data/lib/evt/io.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 792dc614f6216687c600f101b8fac515a71fc0249c4ca6af3f880cb71ee17eff
|
4
|
+
data.tar.gz: c64b75645bd2adb22a3947c7b239c9cde05a8fb1ac42a6e08f2cfe653bc20a84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '016090b4ba576eb10896099d3879445d3c65d3b8f6d9475731786639282c5e7f37ba1029e6d1201b165f9bfbf20193fb13017b5ea6af90792b60989f33691899'
|
7
|
+
data.tar.gz: 83d15ffca0e28b5c96f241197bbd97eabe1a935e01f71c6e4bb94a2eb9ad413148b2318d1b55a4df4b11444e989508b32cd7da9f1b19b839512d13b92b7034b9
|
@@ -0,0 +1,51 @@
|
|
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' }
|
16
|
+
- { os: ubuntu-20.04, ruby: ruby-head }
|
17
|
+
- { os: macos-11.0, ruby: '3.0' }
|
18
|
+
- { os: macos-11.0, ruby: ruby-head }
|
19
|
+
- { os: windows-2019, ruby: mingw }
|
20
|
+
- { os: windows-2019, ruby: mswin }
|
21
|
+
name: ${{ matrix.os }} ${{ matrix.ruby }}
|
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
|
+
run: rake compile
|
36
|
+
- name: Test
|
37
|
+
run: rake
|
38
|
+
build:
|
39
|
+
runs-on: ubuntu-20.04
|
40
|
+
steps:
|
41
|
+
- uses: actions/checkout@v2
|
42
|
+
- uses: ruby/setup-ruby@master
|
43
|
+
with:
|
44
|
+
ruby-version: '3.0'
|
45
|
+
bundler-cache: false
|
46
|
+
- name: Install Dependencies
|
47
|
+
run: |
|
48
|
+
gem install bundler
|
49
|
+
bundle install --jobs 4 --retry 3
|
50
|
+
- name: Build
|
51
|
+
run: gem build evt.gemspec
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,30 @@
|
|
1
|
-
#
|
1
|
+
# Evt
|
2
2
|
|
3
|
-
|
3
|
+
The Event Library that designed for Ruby 3.0.
|
4
4
|
|
5
|
-
|
5
|
+
**This gem is still under development, APIs and features are not stable. Advices and PRs are highly welcome.**
|
6
6
|
|
7
|
-
|
7
|
+
![CI Tests](https://github.com/dsh0416/evt/workflows/CI%20Tests/badge.svg)
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
### IO Backend Support
|
14
|
+
|
15
|
+
| | Linux | Windows | macOS | FreeBSD |
|
16
|
+
| --------------- | ----------- | ------------| ----------- | ----------- |
|
17
|
+
| io_uring | ✅ (See 1) | ❌ | ❌ | ❌ |
|
18
|
+
| epoll | ✅ (See 2) | ❌ | ❌ | ❌ |
|
19
|
+
| kqueue | ❌ | ❌ | ✅ (⚠️ See 5) | ✅ |
|
20
|
+
| IOCP | ❌ | ❌ (⚠️See 3) | ❌ | ❌ |
|
21
|
+
| Ruby (`select`) | ✅ Fallback | ✅ (⚠️See 4) | ✅ Fallback | ✅ Fallback |
|
22
|
+
|
23
|
+
1. when liburing is installed
|
24
|
+
2. when kernel version >= 2.6.8
|
25
|
+
3. WOULD NOT WORK until `FILE_FLAG_OVERLAPPED` is included in I/O initialization process.
|
26
|
+
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).
|
27
|
+
5. `kqueue` performance in Darwin is very poor. **MAY BE DISABLED IN THE FUTURE.**
|
8
28
|
|
9
29
|
## Install
|
10
30
|
|
@@ -18,17 +38,34 @@ gem install evt
|
|
18
38
|
require 'evt'
|
19
39
|
|
20
40
|
rd, wr = IO.pipe
|
21
|
-
|
41
|
+
scheduler = Evt::Scheduler.new
|
22
42
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
43
|
+
Fiber.set_scheduler scheduler
|
44
|
+
|
45
|
+
Fiber.schedule do
|
46
|
+
message = rd.read(20)
|
47
|
+
puts message
|
48
|
+
rd.close
|
49
|
+
end
|
50
|
+
|
51
|
+
Fiber.schedule do
|
52
|
+
wr.write("Hello World")
|
53
|
+
wr.close
|
27
54
|
end
|
28
55
|
|
29
|
-
|
30
|
-
fiber.resume
|
31
|
-
Thread.current.scheduler.run
|
56
|
+
scheduler.run
|
32
57
|
|
33
|
-
|
58
|
+
# "Hello World"
|
34
59
|
```
|
60
|
+
|
61
|
+
## Roadmap
|
62
|
+
|
63
|
+
- [x] Support epoll/kqueue/select
|
64
|
+
- [x] Upgrade to the latest Scheduler API
|
65
|
+
- [x] Support io_uring
|
66
|
+
- [x] Support iov features of io_uring
|
67
|
+
- [x] Support IOCP (**NOT ENABLED YET**)
|
68
|
+
- [x] Setup tests with Ruby 3
|
69
|
+
- [ ] Support IOCP with iov features
|
70
|
+
- [ ] Setup more tests for production purpose
|
71
|
+
- [ ] Documentation for usages
|
data/evt.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
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.
|
13
|
+
spec.required_ruby_version = '>= 2.8.0.dev'
|
14
14
|
|
15
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
16
16
|
spec.metadata["source_code_uri"] = "https://github.com/dsh0416/evt"
|
@@ -18,7 +18,7 @@ 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|spec|features|.vscode)/}) }
|
22
22
|
end
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
spec.extensions = ['ext/evt/extconf.rb']
|
data/ext/evt/epoll.h
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#ifndef EPOLL_H
|
2
|
+
#define EPOLL_G
|
3
|
+
#include "evt.h"
|
4
|
+
|
5
|
+
#if HAVE_SYS_EPOLL_H
|
6
|
+
VALUE method_scheduler_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_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_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_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 = (struct epoll_event*) xmalloc(sizeof(struct epoll_event) * 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
|
+
|
83
|
+
xfree(events);
|
84
|
+
return result;
|
85
|
+
}
|
86
|
+
|
87
|
+
VALUE method_scheduler_backend(VALUE klass) {
|
88
|
+
return rb_str_new_cstr("epoll");
|
89
|
+
}
|
90
|
+
#endif
|
91
|
+
#endif
|
data/ext/evt/evt.c
CHANGED
@@ -1,218 +1,34 @@
|
|
1
|
+
#ifndef EVT_C
|
2
|
+
#define EVT_C
|
3
|
+
|
1
4
|
#include "evt.h"
|
2
5
|
|
3
6
|
void Init_evt_ext()
|
4
7
|
{
|
5
8
|
Evt = rb_define_module("Evt");
|
6
9
|
Scheduler = rb_define_class_under(Evt, "Scheduler", rb_cObject);
|
10
|
+
Payload = rb_define_class_under(Scheduler, "Payload", rb_cObject);
|
11
|
+
Fiber = rb_define_class("Fiber", rb_cObject);
|
7
12
|
rb_define_singleton_method(Scheduler, "backend", method_scheduler_backend, 0);
|
8
13
|
rb_define_method(Scheduler, "init_selector", method_scheduler_init, 0);
|
9
14
|
rb_define_method(Scheduler, "register", method_scheduler_register, 2);
|
10
15
|
rb_define_method(Scheduler, "deregister", method_scheduler_deregister, 1);
|
11
16
|
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
17
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
18
|
+
#if HAVELIBURING_H
|
19
|
+
rb_define_method(Scheduler, "io_read", method_scheduler_io_read, 4);
|
20
|
+
rb_define_method(Scheduler, "io_write", method_scheduler_io_read, 4);
|
21
|
+
#endif
|
22
|
+
}
|
23
|
+
|
24
|
+
#if HAVE_LIBURING_H
|
25
|
+
#include "uring.h"
|
26
|
+
#elif HAVE_SYS_EPOLL_H
|
27
|
+
#include "epoll.h"
|
28
|
+
#elif HAVE_SYS_EVENT_H
|
29
|
+
#include "kqueue.h"
|
30
|
+
#elif HAVE_WINDOWS_H
|
31
|
+
#include "select.h"
|
32
|
+
// #include "iocp.h"
|
33
|
+
#endif
|
34
|
+
#endif
|