polyphony 0.73.1 → 0.74
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 +13 -10
- data/.github/workflows/test_io_uring.yml +32 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +10 -7
- data/bin/pdbg +0 -0
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/ext/polyphony/backend_common.c +75 -11
- data/ext/polyphony/backend_common.h +7 -0
- data/ext/polyphony/backend_io_uring.c +226 -106
- data/ext/polyphony/backend_io_uring_context.c +1 -0
- data/ext/polyphony/backend_io_uring_context.h +2 -1
- data/ext/polyphony/backend_libev.c +7 -9
- data/ext/polyphony/event.c +5 -2
- data/ext/polyphony/polyphony.c +10 -1
- data/ext/polyphony/polyphony.h +2 -0
- data/ext/polyphony/queue.c +10 -5
- data/ext/polyphony/runqueue_ring_buffer.c +3 -1
- data/ext/polyphony/socket_extensions.c +5 -2
- data/lib/polyphony/extensions/fiber.rb +58 -0
- data/lib/polyphony/extensions/socket.rb +17 -5
- data/lib/polyphony/extensions/thread.rb +9 -3
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +2 -1
- data/test/test_backend.rb +3 -5
- data/test/test_global_api.rb +10 -14
- data/test/test_io.rb +2 -2
- data/test/test_kernel.rb +2 -2
- data/test/test_socket.rb +35 -2
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +3 -3
- data/test/test_timer.rb +1 -1
- metadata +8 -7
@@ -697,10 +697,13 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
697
697
|
Backend_t *backend;
|
698
698
|
struct libev_io watcher;
|
699
699
|
rb_io_t *fptr;
|
700
|
-
struct
|
701
|
-
|
700
|
+
struct sockaddr *ai_addr;
|
701
|
+
int ai_addrlen;
|
702
702
|
VALUE switchpoint_result = Qnil;
|
703
703
|
VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
|
704
|
+
|
705
|
+
ai_addrlen = backend_getaddrinfo(host, port, &ai_addr);
|
706
|
+
|
704
707
|
if (underlying_sock != Qnil) sock = underlying_sock;
|
705
708
|
|
706
709
|
GetBackend(self, backend);
|
@@ -708,12 +711,8 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
708
711
|
io_verify_blocking_mode(fptr, sock, Qfalse);
|
709
712
|
watcher.fiber = Qnil;
|
710
713
|
|
711
|
-
addr.sin_family = AF_INET;
|
712
|
-
addr.sin_addr.s_addr = inet_addr(host_buf);
|
713
|
-
addr.sin_port = htons(NUM2INT(port));
|
714
|
-
|
715
714
|
backend->base.op_count++;
|
716
|
-
int result = connect(fptr->fd,
|
715
|
+
int result = connect(fptr->fd, ai_addr, ai_addrlen);
|
717
716
|
if (result < 0) {
|
718
717
|
int e = errno;
|
719
718
|
if (e != EINPROGRESS) rb_syserr_fail(e, strerror(e));
|
@@ -1156,7 +1155,6 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
1156
1155
|
while (1) {
|
1157
1156
|
uint64_t now_ns = current_time_ns();
|
1158
1157
|
if (next_time_ns == 0) next_time_ns = now_ns + interval_ns;
|
1159
|
-
double sleep_duration = ((double)(next_time_ns - now_ns))/1e9;
|
1160
1158
|
|
1161
1159
|
if (next_time_ns > now_ns) {
|
1162
1160
|
double sleep_duration = ((double)(next_time_ns - now_ns))/1e9;
|
@@ -1370,7 +1368,7 @@ inline VALUE Backend_run_idle_tasks(VALUE self) {
|
|
1370
1368
|
return self;
|
1371
1369
|
}
|
1372
1370
|
|
1373
|
-
inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct libev_rw_io *watcher, VALUE *result) {
|
1371
|
+
static inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct libev_rw_io *watcher, VALUE *result) {
|
1374
1372
|
char *buf = RSTRING_PTR(str);
|
1375
1373
|
int len = RSTRING_LEN(str);
|
1376
1374
|
int left = len;
|
data/ext/polyphony/event.c
CHANGED
@@ -59,14 +59,17 @@ VALUE Event_signal(int argc, VALUE *argv, VALUE self) {
|
|
59
59
|
|
60
60
|
VALUE Event_await(VALUE self) {
|
61
61
|
Event_t *event;
|
62
|
+
VALUE switchpoint_result;
|
63
|
+
VALUE backend;
|
64
|
+
|
62
65
|
GetEvent(self, event);
|
63
66
|
|
64
67
|
if (event->waiting_fiber != Qnil)
|
65
68
|
rb_raise(rb_eRuntimeError, "Event is already awaited by another fiber");
|
66
69
|
|
67
|
-
|
70
|
+
backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
68
71
|
event->waiting_fiber = rb_fiber_current();
|
69
|
-
|
72
|
+
switchpoint_result = Backend_wait_event(backend, Qnil);
|
70
73
|
event->waiting_fiber = Qnil;
|
71
74
|
|
72
75
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -9,16 +9,18 @@ ID ID_clear;
|
|
9
9
|
ID ID_each;
|
10
10
|
ID ID_inspect;
|
11
11
|
ID ID_invoke;
|
12
|
-
ID ID_new;
|
13
12
|
ID ID_ivar_blocking_mode;
|
14
13
|
ID ID_ivar_io;
|
15
14
|
ID ID_ivar_parked;
|
16
15
|
ID ID_ivar_runnable;
|
17
16
|
ID ID_ivar_running;
|
18
17
|
ID ID_ivar_thread;
|
18
|
+
ID ID_new;
|
19
|
+
ID ID_raise;
|
19
20
|
ID ID_size;
|
20
21
|
ID ID_signal;
|
21
22
|
ID ID_switch_fiber;
|
23
|
+
ID ID_to_s;
|
22
24
|
ID ID_transfer;
|
23
25
|
ID ID_R;
|
24
26
|
ID ID_W;
|
@@ -123,6 +125,10 @@ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
|
123
125
|
return Backend_write_m(argc, argv, BACKEND());
|
124
126
|
}
|
125
127
|
|
128
|
+
VALUE Polyphony_backend_close(VALUE self, VALUE io) {
|
129
|
+
return Backend_close(BACKEND(), io);
|
130
|
+
}
|
131
|
+
|
126
132
|
void Init_Polyphony() {
|
127
133
|
mPolyphony = rb_define_module("Polyphony");
|
128
134
|
|
@@ -147,6 +153,7 @@ void Init_Polyphony() {
|
|
147
153
|
rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
|
148
154
|
rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
|
149
155
|
rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
|
156
|
+
rb_define_singleton_method(mPolyphony, "backend_close", Polyphony_backend_close, 1);
|
150
157
|
|
151
158
|
rb_define_global_function("snooze", Polyphony_snooze, 0);
|
152
159
|
rb_define_global_function("suspend", Polyphony_suspend, 0);
|
@@ -166,8 +173,10 @@ void Init_Polyphony() {
|
|
166
173
|
ID_ivar_running = rb_intern("@running");
|
167
174
|
ID_ivar_thread = rb_intern("@thread");
|
168
175
|
ID_new = rb_intern("new");
|
176
|
+
ID_raise = rb_intern("raise");
|
169
177
|
ID_signal = rb_intern("signal");
|
170
178
|
ID_size = rb_intern("size");
|
171
179
|
ID_switch_fiber = rb_intern("switch_fiber");
|
180
|
+
ID_to_s = rb_intern("to_s");
|
172
181
|
ID_transfer = rb_intern("transfer");
|
173
182
|
}
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -57,6 +57,7 @@ extern ID ID_raise;
|
|
57
57
|
extern ID ID_signal;
|
58
58
|
extern ID ID_size;
|
59
59
|
extern ID ID_switch_fiber;
|
60
|
+
extern ID ID_to_s;
|
60
61
|
extern ID ID_transfer;
|
61
62
|
|
62
63
|
extern VALUE SYM_fiber_create;
|
@@ -112,6 +113,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise);
|
|
112
113
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
|
113
114
|
VALUE Backend_waitpid(VALUE self, VALUE pid);
|
114
115
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
|
116
|
+
VALUE Backend_close(VALUE self, VALUE io);
|
115
117
|
|
116
118
|
VALUE Backend_poll(VALUE self, VALUE blocking);
|
117
119
|
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
data/ext/polyphony/queue.c
CHANGED
@@ -121,24 +121,27 @@ VALUE Queue_unshift(VALUE self, VALUE value) {
|
|
121
121
|
|
122
122
|
VALUE Queue_shift(VALUE self) {
|
123
123
|
Queue_t *queue;
|
124
|
-
GetQueue(self, queue);
|
125
|
-
|
126
124
|
VALUE fiber = rb_fiber_current();
|
127
125
|
VALUE thread = rb_thread_current();
|
128
126
|
VALUE backend = rb_ivar_get(thread, ID_ivar_backend);
|
127
|
+
VALUE value;
|
128
|
+
|
129
|
+
GetQueue(self, queue);
|
129
130
|
|
130
131
|
while (1) {
|
132
|
+
VALUE switchpoint_result;
|
133
|
+
|
131
134
|
if (queue->values.count) Fiber_make_runnable(fiber, Qnil);
|
132
135
|
|
133
136
|
ring_buffer_push(&queue->shift_queue, fiber);
|
134
|
-
|
137
|
+
switchpoint_result = Backend_wait_event(backend, Qnil);
|
135
138
|
ring_buffer_delete(&queue->shift_queue, fiber);
|
136
139
|
|
137
140
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
138
141
|
RB_GC_GUARD(switchpoint_result);
|
139
142
|
if (queue->values.count) break;
|
140
143
|
}
|
141
|
-
|
144
|
+
value = ring_buffer_shift(&queue->values);
|
142
145
|
if ((queue->capacity) && (queue->capacity > queue->values.count))
|
143
146
|
queue_schedule_first_blocked_fiber(&queue->push_queue);
|
144
147
|
RB_GC_GUARD(value);
|
@@ -206,9 +209,11 @@ VALUE Queue_shift_each(VALUE self) {
|
|
206
209
|
|
207
210
|
VALUE Queue_shift_all(VALUE self) {
|
208
211
|
Queue_t *queue;
|
212
|
+
VALUE result;
|
213
|
+
|
209
214
|
GetQueue(self, queue);
|
210
215
|
|
211
|
-
|
216
|
+
result = ring_buffer_shift_all(&queue->values);
|
212
217
|
if (queue->capacity) queue_schedule_blocked_fibers_to_capacity(queue);
|
213
218
|
return result;
|
214
219
|
}
|
@@ -24,9 +24,11 @@ inline void runqueue_ring_buffer_clear(runqueue_ring_buffer *buffer) {
|
|
24
24
|
static runqueue_entry nil_runqueue_entry = {(Qnil), (Qnil)};
|
25
25
|
|
26
26
|
inline runqueue_entry runqueue_ring_buffer_shift(runqueue_ring_buffer *buffer) {
|
27
|
+
runqueue_entry value;
|
28
|
+
|
27
29
|
if (buffer->count == 0) return nil_runqueue_entry;
|
28
30
|
|
29
|
-
|
31
|
+
value = buffer->entries[buffer->head];
|
30
32
|
buffer->head = (buffer->head + 1) % buffer->size;
|
31
33
|
buffer->count--;
|
32
34
|
return value;
|
@@ -17,10 +17,13 @@ VALUE Socket_double_chevron(VALUE self, VALUE msg) {
|
|
17
17
|
}
|
18
18
|
|
19
19
|
void Init_SocketExtensions() {
|
20
|
+
VALUE cSocket;
|
21
|
+
VALUE cTCPSocket;
|
22
|
+
|
20
23
|
rb_require("socket");
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
|
26
|
+
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
24
27
|
|
25
28
|
rb_define_method(cSocket, "send", Socket_send, 2);
|
26
29
|
rb_define_method(cTCPSocket, "send", Socket_send, 2);
|
@@ -5,17 +5,40 @@ require_relative '../core/exceptions'
|
|
5
5
|
module Polyphony
|
6
6
|
# Fiber control API
|
7
7
|
module FiberControl
|
8
|
+
# Returns the fiber's monitoring mailbox queue, used for receiving fiber
|
9
|
+
# monitoring messages.
|
10
|
+
#
|
11
|
+
# @return [Polyphony::Queue] Monitoring mailbox queue
|
8
12
|
def monitor_mailbox
|
9
13
|
@monitor_mailbox ||= Polyphony::Queue.new
|
10
14
|
end
|
11
15
|
|
16
|
+
# call-seq:
|
17
|
+
# fiber.stop(value = nil) -> fiber
|
18
|
+
# Fiber.interrupt(value = nil) -> fiber
|
19
|
+
#
|
20
|
+
# Stops the fiber by raising a Polyphony::MoveOn exception. The given value
|
21
|
+
# will become the fiber's return value.
|
22
|
+
#
|
23
|
+
# @param value [any] Fiber's eventual return value
|
24
|
+
# @return [Fiber] fiber
|
12
25
|
def interrupt(value = nil)
|
13
26
|
return if @running == false
|
14
27
|
|
15
28
|
schedule Polyphony::MoveOn.new(value)
|
29
|
+
self
|
16
30
|
end
|
17
31
|
alias_method :stop, :interrupt
|
18
32
|
|
33
|
+
# call-seq:
|
34
|
+
# fiber.reset(value = nil) -> fiber
|
35
|
+
# fiber.restart(value = nil) -> fiber
|
36
|
+
#
|
37
|
+
# Restarts the fiber, with the given value serving as the first value passed
|
38
|
+
# to the fiber's block.
|
39
|
+
#
|
40
|
+
# @param value [any] value passed to fiber block
|
41
|
+
# @return [Fiber] restarted fiber
|
19
42
|
def restart(value = nil)
|
20
43
|
raise "Can't restart main fiber" if @main
|
21
44
|
|
@@ -31,32 +54,58 @@ module Polyphony
|
|
31
54
|
end
|
32
55
|
alias_method :reset, :restart
|
33
56
|
|
57
|
+
# Stops a fiber by raising a Polyphony::Cancel exception.
|
58
|
+
#
|
59
|
+
# @return [Fiber] fiber
|
34
60
|
def cancel
|
35
61
|
return if @running == false
|
36
62
|
|
37
63
|
schedule Polyphony::Cancel.new
|
64
|
+
self
|
38
65
|
end
|
39
66
|
|
67
|
+
# Sets the graceful shutdown flag for the fiber.
|
68
|
+
#
|
69
|
+
# @param graceful [bool] Whether or not to perform a graceful shutdown
|
40
70
|
def graceful_shutdown=(graceful)
|
41
71
|
@graceful_shutdown = graceful
|
42
72
|
end
|
43
73
|
|
74
|
+
# Returns the graceful shutdown flag for the fiber.
|
75
|
+
#
|
76
|
+
# @return [bool]
|
44
77
|
def graceful_shutdown?
|
45
78
|
@graceful_shutdown
|
46
79
|
end
|
47
80
|
|
81
|
+
# Terminates the fiber, optionally setting the graceful shutdown flag.
|
82
|
+
#
|
83
|
+
# @param graceful [bool] Whether to perform a graceful shutdown
|
84
|
+
# @return [Fiber]
|
48
85
|
def terminate(graceful = false)
|
49
86
|
return if @running == false
|
50
87
|
|
51
88
|
@graceful_shutdown = graceful
|
52
89
|
schedule Polyphony::Terminate.new
|
90
|
+
self
|
53
91
|
end
|
54
92
|
|
93
|
+
# call-seq:
|
94
|
+
# fiber.raise(message) -> fiber
|
95
|
+
# fiber.raise(exception_class) -> fiber
|
96
|
+
# fiber.raise(exception_class, exception_message) -> fiber
|
97
|
+
# fiber.raise(exception) -> fiber
|
98
|
+
#
|
99
|
+
# Raises an exception in the context of the fiber.
|
100
|
+
#
|
101
|
+
# @return [Fiber]
|
55
102
|
def raise(*args)
|
56
103
|
error = error_from_raise_args(args)
|
57
104
|
schedule(error)
|
105
|
+
self
|
58
106
|
end
|
59
107
|
|
108
|
+
# :no-doc:
|
60
109
|
def error_from_raise_args(args)
|
61
110
|
case (arg = args.shift)
|
62
111
|
when String then RuntimeError.new(arg)
|
@@ -125,6 +174,9 @@ module Polyphony
|
|
125
174
|
# return values for all terminated fibers. If any of the awaited fibers
|
126
175
|
# terminates with an uncaught exception, `Fiber.await` will await all the
|
127
176
|
# other fibers to terminate, then reraise the exception.
|
177
|
+
#
|
178
|
+
# @param *fibers [Array<Fiber>] fibers to wait for
|
179
|
+
# @return [Array<any>] return values of given fibers
|
128
180
|
def await(*fibers)
|
129
181
|
return [] if fibers.empty?
|
130
182
|
|
@@ -158,6 +210,12 @@ module Polyphony
|
|
158
210
|
end
|
159
211
|
alias_method :join, :await
|
160
212
|
|
213
|
+
# Waits for at least one of the given fibers to terminate, returning an
|
214
|
+
# array containing the first terminated fiber and its return value. If an
|
215
|
+
# exception occurs in one of the given fibers, it will be reraised.
|
216
|
+
#
|
217
|
+
# @param *fibers [Array<Fiber>] Fibers to wait for
|
218
|
+
# @return [Array] Array containing the first terminated fiber and its return value
|
161
219
|
def select(*fibers)
|
162
220
|
return nil if fibers.empty?
|
163
221
|
|
@@ -31,7 +31,7 @@ class ::Socket
|
|
31
31
|
alias_method :orig_read, :read
|
32
32
|
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
33
33
|
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
34
|
-
return Polyphony.backend_recv(self,
|
34
|
+
return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
|
35
35
|
|
36
36
|
buf = +''
|
37
37
|
len = buf.bytesize
|
@@ -120,8 +120,16 @@ class ::TCPSocket
|
|
120
120
|
|
121
121
|
attr_reader :io
|
122
122
|
|
123
|
+
def self.open(*args)
|
124
|
+
new(*args)
|
125
|
+
end
|
126
|
+
|
127
|
+
def address_family(host)
|
128
|
+
host =~ /\:\:/ ? Socket::AF_INET6 : Socket::AF_INET
|
129
|
+
end
|
130
|
+
|
123
131
|
def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
|
124
|
-
@io = Socket.new
|
132
|
+
@io = Socket.new address_family(remote_host), Socket::SOCK_STREAM
|
125
133
|
if local_host && local_port
|
126
134
|
addr = Addrinfo.tcp(local_host, local_port)
|
127
135
|
@io.bind(addr)
|
@@ -167,7 +175,7 @@ class ::TCPSocket
|
|
167
175
|
alias_method :orig_read, :read
|
168
176
|
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
169
177
|
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
170
|
-
return Polyphony.backend_recv(self,
|
178
|
+
return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
|
171
179
|
|
172
180
|
buf = +''
|
173
181
|
len = buf.bytesize
|
@@ -223,8 +231,12 @@ end
|
|
223
231
|
|
224
232
|
# Override stock TCPServer code by encapsulating a Socket instance.
|
225
233
|
class ::TCPServer
|
234
|
+
def address_family(host)
|
235
|
+
host =~ /\:\:/ ? Socket::AF_INET6 : Socket::AF_INET
|
236
|
+
end
|
237
|
+
|
226
238
|
def initialize(hostname = nil, port = 0)
|
227
|
-
@io = Socket.new
|
239
|
+
@io = Socket.new address_family(hostname), Socket::SOCK_STREAM
|
228
240
|
@io.bind(Addrinfo.tcp(hostname, port))
|
229
241
|
@io.listen(0)
|
230
242
|
end
|
@@ -259,7 +271,7 @@ class ::UNIXSocket
|
|
259
271
|
alias_method :orig_read, :read
|
260
272
|
def read(maxlen = nil, buf = nil, buf_pos = 0)
|
261
273
|
return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
|
262
|
-
return Polyphony.backend_recv(self,
|
274
|
+
return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
|
263
275
|
|
264
276
|
buf = +''
|
265
277
|
len = buf.bytesize
|
@@ -18,14 +18,20 @@ class ::Thread
|
|
18
18
|
def execute
|
19
19
|
# backend must be created in the context of the new thread, therefore it
|
20
20
|
# cannot be created in Thread#initialize
|
21
|
-
|
21
|
+
raise_error = false
|
22
|
+
begin
|
23
|
+
@backend = Polyphony::Backend.new
|
24
|
+
rescue Exception => e
|
25
|
+
raise_error = true
|
26
|
+
raise e
|
27
|
+
end
|
22
28
|
setup
|
23
29
|
@ready = true
|
24
30
|
result = @block.(*@args)
|
25
31
|
rescue Polyphony::MoveOn, Polyphony::Terminate => e
|
26
32
|
result = e.value
|
27
33
|
rescue Exception => e
|
28
|
-
result = e
|
34
|
+
raise_error ? (raise e) : (result = e)
|
29
35
|
ensure
|
30
36
|
@ready = true
|
31
37
|
finalize(result)
|
@@ -48,7 +54,7 @@ class ::Thread
|
|
48
54
|
@result = result
|
49
55
|
signal_waiters(result)
|
50
56
|
end
|
51
|
-
@backend
|
57
|
+
@backend&.finalize
|
52
58
|
end
|
53
59
|
|
54
60
|
def signal_waiters(result)
|
data/lib/polyphony/version.rb
CHANGED
data/lib/polyphony.rb
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'fiber'
|
4
4
|
require_relative './polyphony_ext'
|
5
|
-
require_relative './polyphony/extensions'
|
5
|
+
require_relative './polyphony/extensions/thread'
|
6
6
|
|
7
7
|
Thread.current.setup_fiber_scheduling
|
8
8
|
Thread.current.backend = Polyphony::Backend.new
|
9
9
|
|
10
|
+
require_relative './polyphony/extensions'
|
10
11
|
require_relative './polyphony/core/exceptions'
|
11
12
|
require_relative './polyphony/core/global_api'
|
12
13
|
require_relative './polyphony/core/resource_pool'
|
data/test/test_backend.rb
CHANGED
@@ -243,16 +243,14 @@ class BackendTest < MiniTest::Test
|
|
243
243
|
end
|
244
244
|
|
245
245
|
def test_timer_loop
|
246
|
-
|
247
|
-
|
248
|
-
i = 0
|
246
|
+
counter = 0
|
249
247
|
f = spin do
|
250
|
-
@backend.timer_loop(0.01) {
|
248
|
+
@backend.timer_loop(0.01) { counter += 1 }
|
251
249
|
end
|
252
250
|
@backend.sleep(0.05)
|
253
251
|
f.stop
|
254
252
|
f.await # TODO: check why this test sometimes segfaults if we don't a<wait fiber
|
255
|
-
assert_in_range 4..6,
|
253
|
+
assert_in_range 4..6, counter if IS_LINUX
|
256
254
|
end
|
257
255
|
|
258
256
|
class MyTimeoutException < Exception
|
data/test/test_global_api.rb
CHANGED
@@ -162,7 +162,7 @@ class MoveOnAfterTest < MiniTest::Test
|
|
162
162
|
end
|
163
163
|
t1 = Time.now
|
164
164
|
assert_equal 1, o
|
165
|
-
assert_in_range 0.008..0.015, t1 - t0
|
165
|
+
assert_in_range 0.008..0.015, t1 - t0 if IS_LINUX
|
166
166
|
|
167
167
|
t0 = Time.now
|
168
168
|
o = move_on_after(0.05, with_value: 1) do
|
@@ -172,7 +172,7 @@ class MoveOnAfterTest < MiniTest::Test
|
|
172
172
|
end
|
173
173
|
t1 = Time.now
|
174
174
|
assert_equal 2, o
|
175
|
-
assert_in_range 0.008..0.013, t1 - t0
|
175
|
+
assert_in_range 0.008..0.013, t1 - t0 if IS_LINUX
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
@@ -297,7 +297,7 @@ class SpinLoopTest < MiniTest::Test
|
|
297
297
|
f = spin_loop(rate: 100) { buffer << (counter += 1) }
|
298
298
|
sleep 0.02
|
299
299
|
f.stop
|
300
|
-
assert_in_range 1..3, counter
|
300
|
+
assert_in_range 1..3, counter if IS_LINUX
|
301
301
|
end
|
302
302
|
|
303
303
|
def test_spin_loop_with_interval
|
@@ -307,7 +307,7 @@ class SpinLoopTest < MiniTest::Test
|
|
307
307
|
f = spin_loop(interval: 0.01) { buffer << (counter += 1) }
|
308
308
|
sleep 0.02
|
309
309
|
f.stop
|
310
|
-
assert_in_range 1..3, counter
|
310
|
+
assert_in_range 1..3, counter if IS_LINUX
|
311
311
|
end
|
312
312
|
|
313
313
|
def test_spin_loop_break
|
@@ -386,10 +386,10 @@ class ThrottledLoopTest < MiniTest::Test
|
|
386
386
|
counter = 0
|
387
387
|
t0 = Time.now
|
388
388
|
f = spin do
|
389
|
-
throttled_loop(
|
389
|
+
throttled_loop(10) { buffer << (counter += 1) }
|
390
390
|
end
|
391
|
-
sleep 0.
|
392
|
-
assert_in_range 2..4, counter
|
391
|
+
sleep 0.3
|
392
|
+
assert_in_range 2..4, counter if IS_LINUX
|
393
393
|
end
|
394
394
|
|
395
395
|
def test_throttled_loop_with_count
|
@@ -417,8 +417,6 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
417
417
|
end
|
418
418
|
|
419
419
|
def test_every
|
420
|
-
skip unless IS_LINUX
|
421
|
-
|
422
420
|
buffer = []
|
423
421
|
t0 = Time.now
|
424
422
|
f = spin do
|
@@ -426,12 +424,10 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
426
424
|
end
|
427
425
|
sleep 0.05
|
428
426
|
f.stop
|
429
|
-
assert_in_range 4..6, buffer.size
|
427
|
+
assert_in_range 4..6, buffer.size if IS_LINUX
|
430
428
|
end
|
431
429
|
|
432
430
|
def test_every_with_slow_op
|
433
|
-
skip unless IS_LINUX
|
434
|
-
|
435
431
|
buffer = []
|
436
432
|
t0 = Time.now
|
437
433
|
f = spin do
|
@@ -439,14 +435,14 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
439
435
|
end
|
440
436
|
sleep 0.15
|
441
437
|
f.stop
|
442
|
-
assert_in_range 2..3, buffer.size
|
438
|
+
assert_in_range 2..3, buffer.size if IS_LINUX
|
443
439
|
end
|
444
440
|
|
445
441
|
def test_sleep
|
446
442
|
t0 = Time.now
|
447
443
|
sleep 0.1
|
448
444
|
elapsed = Time.now - t0
|
449
|
-
|
445
|
+
assert_in_range 0.05..0.15, elapsed if IS_LINUX
|
450
446
|
|
451
447
|
f = spin { sleep }
|
452
448
|
snooze
|
data/test/test_io.rb
CHANGED
@@ -354,9 +354,9 @@ class IOClassMethodsTest < MiniTest::Test
|
|
354
354
|
skip unless IS_LINUX
|
355
355
|
|
356
356
|
counter = 0
|
357
|
-
timer = spin { throttled_loop(
|
357
|
+
timer = spin { throttled_loop(20) { counter += 1 } }
|
358
358
|
|
359
|
-
IO.popen('sleep 0.
|
359
|
+
IO.popen('sleep 0.5') { |io| io.read(8192) }
|
360
360
|
assert(counter >= 5)
|
361
361
|
|
362
362
|
result = nil
|
data/test/test_kernel.rb
CHANGED
@@ -51,8 +51,8 @@ class KernelTest < MiniTest::Test
|
|
51
51
|
counter = 0
|
52
52
|
timer = spin { throttled_loop(200) { counter += 1 } }
|
53
53
|
|
54
|
-
`sleep 0.
|
55
|
-
|
54
|
+
`sleep 0.05`
|
55
|
+
assert_in_range 8..14, counter if IS_LINUX
|
56
56
|
|
57
57
|
result = `echo "hello"`
|
58
58
|
assert_equal "hello\n", result
|
data/test/test_socket.rb
CHANGED
@@ -9,9 +9,9 @@ class SocketTest < MiniTest::Test
|
|
9
9
|
super
|
10
10
|
end
|
11
11
|
|
12
|
-
def start_tcp_server_on_random_port
|
12
|
+
def start_tcp_server_on_random_port(host = '127.0.0.1')
|
13
13
|
port = rand(1100..60000)
|
14
|
-
server = TCPServer.new(
|
14
|
+
server = TCPServer.new(host, port)
|
15
15
|
[port, server]
|
16
16
|
rescue Errno::EADDRINUSE
|
17
17
|
retry
|
@@ -40,6 +40,39 @@ class SocketTest < MiniTest::Test
|
|
40
40
|
server&.close
|
41
41
|
end
|
42
42
|
|
43
|
+
def test_tcpsocket_open_with_hostname
|
44
|
+
client = TCPSocket.open('google.com', 80)
|
45
|
+
client.write("GET / HTTP/1.0\r\nHost: google.com\r\n\r\n")
|
46
|
+
result = nil
|
47
|
+
move_on_after(1) {
|
48
|
+
result = client.read
|
49
|
+
}
|
50
|
+
assert result =~ /HTTP\/1.0 301 Moved Permanently/
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_tcp_ipv6
|
54
|
+
port, server = start_tcp_server_on_random_port('::1')
|
55
|
+
server_fiber = spin do
|
56
|
+
while (socket = server.accept)
|
57
|
+
spin do
|
58
|
+
while (data = socket.gets(8192))
|
59
|
+
socket << data
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
snooze
|
66
|
+
client = TCPSocket.new('::1', port)
|
67
|
+
client.write("1234\n")
|
68
|
+
assert_equal "1234\n", client.recv(8192)
|
69
|
+
client.close
|
70
|
+
ensure
|
71
|
+
server_fiber&.stop
|
72
|
+
server_fiber&.await
|
73
|
+
server&.close
|
74
|
+
end
|
75
|
+
|
43
76
|
def test_read
|
44
77
|
port, server = start_tcp_server_on_random_port
|
45
78
|
server_fiber = spin do
|
data/test/test_thread_pool.rb
CHANGED