evt 0.1.4 → 0.2.0
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 +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
|
+

|
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
|