polyphony 0.45.0 → 0.45.1
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/.rubocop.yml +1 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +9 -1
- data/TODO.md +6 -7
- data/examples/adapters/redis_client.rb +3 -1
- data/examples/adapters/redis_pubsub_perf.rb +11 -8
- data/examples/adapters/sequel_mysql.rb +1 -1
- data/examples/adapters/sequel_pg.rb +24 -0
- data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
- data/examples/core/{xx-channels.rb → channels.rb} +0 -0
- data/examples/core/deferring-an-operation.rb +16 -0
- data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
- data/examples/core/{xx-forking.rb → forking.rb} +1 -1
- data/examples/core/handling-signals.rb +11 -0
- data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
- data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
- data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
- data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
- data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
- data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
- data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
- data/examples/core/supervisor.rb +20 -0
- data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
- data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
- data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
- data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
- data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
- data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
- data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
- data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
- data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
- data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
- data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
- data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
- data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
- data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
- data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
- data/examples/io/{xx-irb.rb → irb.rb} +0 -0
- data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
- data/examples/io/{xx-open.rb → open.rb} +0 -0
- data/examples/io/{xx-pry.rb → pry.rb} +0 -0
- data/examples/io/{xx-rack_server.rb → rack_server.rb} +0 -0
- data/examples/io/{xx-system.rb → system.rb} +1 -1
- data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
- data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
- data/examples/io/tunnel.rb +6 -1
- data/examples/io/{xx-zip.rb → zip.rb} +0 -0
- data/examples/performance/fiber_transfer.rb +2 -1
- data/examples/performance/fs_read.rb +5 -6
- data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
- data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
- data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
- data/examples/performance/thread_pool_perf.rb +6 -7
- data/ext/polyphony/backend.h +0 -1
- data/ext/polyphony/libev_backend.c +69 -68
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +0 -13
- data/ext/polyphony/polyphony_ext.c +1 -2
- data/ext/polyphony/queue.c +3 -4
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/thread.c +3 -4
- data/lib/polyphony/adapters/fs.rb +1 -1
- data/lib/polyphony/adapters/redis.rb +1 -1
- data/lib/polyphony/core/global_api.rb +4 -4
- data/lib/polyphony/core/sync.rb +11 -9
- data/lib/polyphony/extensions/core.rb +1 -6
- data/lib/polyphony/extensions/io.rb +40 -6
- data/lib/polyphony/extensions/socket.rb +11 -2
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +2 -1
- data/test/test_io.rb +16 -0
- data/test/test_socket.rb +17 -0
- data/test/test_throttler.rb +1 -0
- metadata +58 -72
- data/examples/adapters/concurrent-ruby.rb +0 -9
- data/examples/core/04-handling-signals.rb +0 -19
- data/examples/core/xx-at_exit.rb +0 -29
- data/examples/core/xx-backend.rb +0 -102
- data/examples/core/xx-caller.rb +0 -12
- data/examples/core/xx-daemon.rb +0 -14
- data/examples/core/xx-deadlock.rb +0 -8
- data/examples/core/xx-deferring-an-operation.rb +0 -14
- data/examples/core/xx-exception-backtrace.rb +0 -40
- data/examples/core/xx-fork-cleanup.rb +0 -22
- data/examples/core/xx-fork-spin.rb +0 -42
- data/examples/core/xx-fork-terminate.rb +0 -27
- data/examples/core/xx-move_on.rb +0 -23
- data/examples/core/xx-queue-async.rb +0 -120
- data/examples/core/xx-readpartial.rb +0 -18
- data/examples/core/xx-signals.rb +0 -16
- data/examples/core/xx-sleep-forever.rb +0 -9
- data/examples/core/xx-sleeping.rb +0 -25
- data/examples/core/xx-snooze-starve.rb +0 -16
- data/examples/core/xx-spin-fork.rb +0 -49
- data/examples/core/xx-state-machine.rb +0 -51
- data/examples/core/xx-stop.rb +0 -20
- data/examples/core/xx-supervisors.rb +0 -21
- data/examples/core/xx-thread-selector-sleep.rb +0 -51
- data/examples/core/xx-thread-selector-snooze.rb +0 -46
- data/examples/core/xx-thread-snooze.rb +0 -34
- data/examples/core/xx-timer-gc.rb +0 -17
- data/examples/core/xx-trace.rb +0 -79
- data/examples/performance/xx-array.rb +0 -11
- data/examples/performance/xx-fiber-switch.rb +0 -9
- data/examples/performance/xx-snooze.rb +0 -15
- data/examples/xx-spin.rb +0 -32
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -16,23 +16,14 @@ end
|
|
|
16
16
|
zones = %w{
|
|
17
17
|
Europe/London Europe/Paris Europe/Bucharest America/New_York Asia/Bangkok
|
|
18
18
|
}
|
|
19
|
-
# zones.each do |tzone|
|
|
20
|
-
# spin do
|
|
21
|
-
# time = get_time(tzone)
|
|
22
|
-
# puts "Time in #{tzone}: #{time}"
|
|
23
|
-
# end
|
|
24
|
-
# end
|
|
25
|
-
|
|
26
|
-
# suspend
|
|
27
19
|
|
|
28
20
|
def get_times(zones)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
s.spin { [tzone, get_time(tzone)] }
|
|
32
|
-
end
|
|
21
|
+
fibers = zones.map do |tzone|
|
|
22
|
+
spin { [tzone, get_time(tzone)] }
|
|
33
23
|
end
|
|
24
|
+
Fiber.await(*fibers)
|
|
34
25
|
end
|
|
35
26
|
|
|
36
|
-
get_times(zones).
|
|
27
|
+
get_times(zones).each do |tzone, time|
|
|
37
28
|
puts "Time in #{tzone}: #{time}"
|
|
38
29
|
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
data/examples/io/tunnel.rb
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
4
|
require 'polyphony'
|
|
5
5
|
|
|
6
|
+
if ARGV.size < 2
|
|
7
|
+
puts "Usage: ruby examples/tunnel.rb <port1> <port2>"
|
|
8
|
+
exit
|
|
9
|
+
end
|
|
10
|
+
|
|
6
11
|
Ports = ARGV[0..1]
|
|
7
12
|
EndPoints = []
|
|
8
13
|
|
|
@@ -24,7 +29,7 @@ def endpoint_loop(idx, peer_idx)
|
|
|
24
29
|
conn.binmode
|
|
25
30
|
EndPoints[idx] = conn
|
|
26
31
|
log "Client connected on port #{port} (#{conn.remote_address.inspect})"
|
|
27
|
-
|
|
32
|
+
conn.read_loop do |data|
|
|
28
33
|
peer = EndPoints[peer_idx]
|
|
29
34
|
if peer
|
|
30
35
|
peer << data
|
|
File without changes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
4
|
require 'polyphony'
|
|
5
|
-
require 'polyphony/fs'
|
|
5
|
+
require 'polyphony/adapters/fs'
|
|
6
6
|
|
|
7
7
|
def raw_read_file(x)
|
|
8
8
|
t0 = Time.now
|
|
@@ -14,7 +14,7 @@ def threaded_read_file(x, y)
|
|
|
14
14
|
t0 = Time.now
|
|
15
15
|
threads = []
|
|
16
16
|
y.times do
|
|
17
|
-
threads << Thread.new { x.times { IO.orig_read(
|
|
17
|
+
threads << Thread.new { x.times { IO.orig_read(__FILE__) } }
|
|
18
18
|
end
|
|
19
19
|
threads.each(&:join)
|
|
20
20
|
puts "threaded_read_file: #{Time.now - t0}"
|
|
@@ -22,11 +22,10 @@ end
|
|
|
22
22
|
|
|
23
23
|
def thread_pool_read_file(x, y)
|
|
24
24
|
t0 = Time.now
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
s.spin { x.times { IO.read(PATH) } }
|
|
28
|
-
end
|
|
25
|
+
y.times do
|
|
26
|
+
spin { x.times { IO.read(__FILE__) } }
|
|
29
27
|
end
|
|
28
|
+
Fiber.current.await_all_children
|
|
30
29
|
puts "thread_pool_read_file: #{Time.now - t0}"
|
|
31
30
|
end
|
|
32
31
|
|
|
File without changes
|
|
@@ -24,7 +24,7 @@ def handle_client(socket)
|
|
|
24
24
|
parser.on_message_complete = proc do |env|
|
|
25
25
|
reqs << Object.new # parser
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
socket.read_loop do |data|
|
|
28
28
|
parser << data
|
|
29
29
|
while (req = reqs.shift)
|
|
30
30
|
handle_request(socket, req)
|
|
@@ -11,11 +11,7 @@ def handle_client(client)
|
|
|
11
11
|
headers = "Content-Length: #{data.bytesize}\r\n"
|
|
12
12
|
client.write "HTTP/1.1 #{status_code}\r\n#{headers}\r\n#{data}"
|
|
13
13
|
end
|
|
14
|
-
|
|
15
|
-
while data = client.readpartial(8192) rescue nil
|
|
16
|
-
parser << data
|
|
17
|
-
end
|
|
18
|
-
end
|
|
14
|
+
client.read_loop { |data| parser << data }
|
|
19
15
|
client.close
|
|
20
16
|
end
|
|
21
17
|
end
|
|
@@ -10,7 +10,7 @@ def lengthy_op
|
|
|
10
10
|
# Digest::SHA256.digest(IO.read('doc/Promise.html'))
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
X =
|
|
13
|
+
X = 10000
|
|
14
14
|
|
|
15
15
|
def compare_performance
|
|
16
16
|
t0 = Time.now
|
|
@@ -35,20 +35,19 @@ def compare_performance
|
|
|
35
35
|
|
|
36
36
|
acc = 0
|
|
37
37
|
count = 0
|
|
38
|
-
|
|
38
|
+
1.times do |_i|
|
|
39
39
|
t0 = Time.now
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
s.spin { Polyphony::ThreadPool.process { lengthy_op } }
|
|
43
|
-
end
|
|
40
|
+
X.times do
|
|
41
|
+
spin { Polyphony::ThreadPool.process { lengthy_op } }
|
|
44
42
|
end
|
|
43
|
+
Fiber.current.await_all_children
|
|
45
44
|
thread_pool_perf = X / (Time.now - t0)
|
|
46
45
|
acc += thread_pool_perf
|
|
47
46
|
count += 1
|
|
48
47
|
end
|
|
49
48
|
avg_perf = acc / count
|
|
50
49
|
puts format(
|
|
51
|
-
'
|
|
50
|
+
'spin X thread pool performance: %g (X %0.2f)',
|
|
52
51
|
avg_perf,
|
|
53
52
|
avg_perf / native_perf
|
|
54
53
|
)
|
data/ext/polyphony/backend.h
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
// VALUE LibevBackend_accept(VALUE self, VALUE sock);
|
|
9
9
|
// VALUE LibevBackend_accept_loop(VALUE self, VALUE sock);
|
|
10
|
-
// VALUE libev_backend_await(VALUE self);
|
|
11
10
|
// VALUE LibevBackend_connect(VALUE self, VALUE sock, VALUE host, VALUE port);
|
|
12
11
|
// VALUE LibevBackend_finalize(VALUE self);
|
|
13
12
|
// VALUE LibevBackend_post_fork(VALUE self);
|
|
@@ -31,7 +31,7 @@ static const rb_data_type_t LibevBackend_type = {
|
|
|
31
31
|
|
|
32
32
|
static VALUE LibevBackend_allocate(VALUE klass) {
|
|
33
33
|
LibevBackend_t *backend = ALLOC(LibevBackend_t);
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
return TypedData_Wrap_Struct(klass, &LibevBackend_type, backend);
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -93,7 +93,7 @@ VALUE LibevBackend_ref(VALUE self) {
|
|
|
93
93
|
GetLibevBackend(self, backend);
|
|
94
94
|
|
|
95
95
|
backend->ref_count++;
|
|
96
|
-
return self;
|
|
96
|
+
return self;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
VALUE LibevBackend_unref(VALUE self) {
|
|
@@ -101,7 +101,7 @@ VALUE LibevBackend_unref(VALUE self) {
|
|
|
101
101
|
GetLibevBackend(self, backend);
|
|
102
102
|
|
|
103
103
|
backend->ref_count--;
|
|
104
|
-
return self;
|
|
104
|
+
return self;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
int LibevBackend_ref_count(VALUE self) {
|
|
@@ -139,7 +139,7 @@ VALUE LibevBackend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE que
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
backend->run_no_wait_count = 0;
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
COND_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
|
144
144
|
backend->running = 1;
|
|
145
145
|
ev_run(backend->ev_loop, is_nowait ? EVRUN_NOWAIT : EVRUN_ONCE);
|
|
@@ -253,25 +253,32 @@ inline VALUE libev_await(LibevBackend_t *backend) {
|
|
|
253
253
|
return ret;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
VALUE
|
|
257
|
-
LibevBackend_t *backend;
|
|
258
|
-
GetLibevBackend(self, backend);
|
|
259
|
-
return libev_await(backend);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
VALUE libev_io_wait(LibevBackend_t *backend, struct libev_io *watcher, rb_io_t *fptr, int flags) {
|
|
256
|
+
VALUE libev_wait_fd_with_watcher(LibevBackend_t *backend, int fd, struct libev_io *watcher, int events) {
|
|
263
257
|
VALUE switchpoint_result;
|
|
264
258
|
|
|
265
259
|
if (watcher->fiber == Qnil) {
|
|
266
260
|
watcher->fiber = rb_fiber_current();
|
|
267
|
-
ev_io_init(&watcher->io, LibevBackend_io_callback,
|
|
261
|
+
ev_io_init(&watcher->io, LibevBackend_io_callback, fd, events);
|
|
268
262
|
}
|
|
269
263
|
ev_io_start(backend->ev_loop, &watcher->io);
|
|
264
|
+
|
|
270
265
|
switchpoint_result = libev_await(backend);
|
|
266
|
+
|
|
271
267
|
ev_io_stop(backend->ev_loop, &watcher->io);
|
|
268
|
+
RB_GC_GUARD(switchpoint_result);
|
|
269
|
+
return switchpoint_result;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
VALUE libev_wait_fd(LibevBackend_t *backend, int fd, int events, int raise_exception) {
|
|
273
|
+
struct libev_io watcher;
|
|
274
|
+
VALUE switchpoint_result = Qnil;
|
|
275
|
+
watcher.fiber = Qnil;
|
|
276
|
+
|
|
277
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, events);
|
|
272
278
|
|
|
279
|
+
if (raise_exception) TEST_RESUME_EXCEPTION(switchpoint_result);
|
|
273
280
|
RB_GC_GUARD(switchpoint_result);
|
|
274
|
-
return switchpoint_result;
|
|
281
|
+
return switchpoint_result;
|
|
275
282
|
}
|
|
276
283
|
|
|
277
284
|
VALUE libev_snooze() {
|
|
@@ -288,20 +295,19 @@ ID ID_ivar_is_nonblocking;
|
|
|
288
295
|
// benchmarks (with a "hello world" HTTP server) show throughput is improved
|
|
289
296
|
// by 10-13%.
|
|
290
297
|
inline void io_set_nonblock(rb_io_t *fptr, VALUE io) {
|
|
298
|
+
VALUE is_nonblocking = rb_ivar_get(io, ID_ivar_is_nonblocking);
|
|
299
|
+
if (is_nonblocking == Qtrue) return;
|
|
300
|
+
|
|
301
|
+
rb_ivar_set(io, ID_ivar_is_nonblocking, Qtrue);
|
|
302
|
+
|
|
291
303
|
#ifdef _WIN32
|
|
292
|
-
|
|
304
|
+
rb_w32_set_nonblock(fptr->fd);
|
|
293
305
|
#elif defined(F_GETFL)
|
|
294
|
-
|
|
295
|
-
if (
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (oflags == -1) return;
|
|
299
|
-
if (oflags & O_NONBLOCK) return;
|
|
300
|
-
oflags |= O_NONBLOCK;
|
|
301
|
-
fcntl(fptr->fd, F_SETFL, oflags);
|
|
302
|
-
}
|
|
306
|
+
int oflags = fcntl(fptr->fd, F_GETFL);
|
|
307
|
+
if ((oflags == -1) && (oflags & O_NONBLOCK)) return;
|
|
308
|
+
oflags |= O_NONBLOCK;
|
|
309
|
+
fcntl(fptr->fd, F_SETFL, oflags);
|
|
303
310
|
#endif
|
|
304
|
-
return;
|
|
305
311
|
}
|
|
306
312
|
|
|
307
313
|
VALUE LibevBackend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
|
@@ -323,7 +329,7 @@ VALUE LibevBackend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_
|
|
|
323
329
|
rb_io_check_byte_readable(fptr);
|
|
324
330
|
io_set_nonblock(fptr, io);
|
|
325
331
|
watcher.fiber = Qnil;
|
|
326
|
-
|
|
332
|
+
|
|
327
333
|
OBJ_TAINT(str);
|
|
328
334
|
|
|
329
335
|
// Apparently after reopening a closed file, the file position is not reset,
|
|
@@ -340,12 +346,14 @@ VALUE LibevBackend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_
|
|
|
340
346
|
if (n < 0) {
|
|
341
347
|
int e = errno;
|
|
342
348
|
if (e != EWOULDBLOCK && e != EAGAIN) rb_syserr_fail(e, strerror(e));
|
|
343
|
-
|
|
344
|
-
switchpoint_result =
|
|
349
|
+
|
|
350
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_READ);
|
|
351
|
+
|
|
345
352
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
346
353
|
}
|
|
347
354
|
else {
|
|
348
355
|
switchpoint_result = libev_snooze();
|
|
356
|
+
|
|
349
357
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
350
358
|
|
|
351
359
|
if (n == 0) break; // EOF
|
|
@@ -354,7 +362,7 @@ VALUE LibevBackend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_
|
|
|
354
362
|
|
|
355
363
|
if (total == len) {
|
|
356
364
|
if (!dynamic_len) break;
|
|
357
|
-
|
|
365
|
+
|
|
358
366
|
rb_str_resize(str, total);
|
|
359
367
|
rb_str_modify_expand(str, len);
|
|
360
368
|
buf = RSTRING_PTR(str) + total;
|
|
@@ -364,11 +372,12 @@ VALUE LibevBackend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_
|
|
|
364
372
|
else buf += n;
|
|
365
373
|
}
|
|
366
374
|
}
|
|
367
|
-
if (total == 0) return Qnil;
|
|
368
375
|
|
|
369
376
|
io_set_read_length(str, total, shrinkable);
|
|
370
377
|
io_enc_str(str, fptr);
|
|
371
|
-
|
|
378
|
+
|
|
379
|
+
if (total == 0) return Qnil;
|
|
380
|
+
|
|
372
381
|
RB_GC_GUARD(watcher.fiber);
|
|
373
382
|
RB_GC_GUARD(switchpoint_result);
|
|
374
383
|
|
|
@@ -429,22 +438,17 @@ VALUE LibevBackend_read_loop(VALUE self, VALUE io) {
|
|
|
429
438
|
int e = errno;
|
|
430
439
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
431
440
|
|
|
432
|
-
switchpoint_result =
|
|
441
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_READ);
|
|
433
442
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
434
443
|
}
|
|
435
444
|
else {
|
|
436
445
|
switchpoint_result = libev_snooze();
|
|
437
|
-
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
438
446
|
|
|
439
|
-
if (
|
|
447
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
440
448
|
|
|
449
|
+
if (n == 0) break; // EOF
|
|
441
450
|
total = n;
|
|
442
451
|
YIELD_STR();
|
|
443
|
-
Fiber_make_runnable(rb_fiber_current(), Qnil);
|
|
444
|
-
switchpoint_result = Thread_switch_fiber(rb_thread_current());
|
|
445
|
-
if (TEST_EXCEPTION(switchpoint_result)) {
|
|
446
|
-
goto error;
|
|
447
|
-
}
|
|
448
452
|
}
|
|
449
453
|
}
|
|
450
454
|
|
|
@@ -479,7 +483,9 @@ VALUE LibevBackend_write(VALUE self, VALUE io, VALUE str) {
|
|
|
479
483
|
if (n < 0) {
|
|
480
484
|
int e = errno;
|
|
481
485
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
482
|
-
|
|
486
|
+
|
|
487
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
|
|
488
|
+
|
|
483
489
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
484
490
|
}
|
|
485
491
|
else {
|
|
@@ -490,6 +496,7 @@ VALUE LibevBackend_write(VALUE self, VALUE io, VALUE str) {
|
|
|
490
496
|
|
|
491
497
|
if (watcher.fiber == Qnil) {
|
|
492
498
|
switchpoint_result = libev_snooze();
|
|
499
|
+
|
|
493
500
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
494
501
|
}
|
|
495
502
|
|
|
@@ -535,7 +542,8 @@ VALUE LibevBackend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
|
535
542
|
int e = errno;
|
|
536
543
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
537
544
|
|
|
538
|
-
switchpoint_result =
|
|
545
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
|
|
546
|
+
|
|
539
547
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
540
548
|
}
|
|
541
549
|
else {
|
|
@@ -558,6 +566,7 @@ VALUE LibevBackend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
|
558
566
|
}
|
|
559
567
|
if (watcher.fiber == Qnil) {
|
|
560
568
|
switchpoint_result = libev_snooze();
|
|
569
|
+
|
|
561
570
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
562
571
|
}
|
|
563
572
|
|
|
@@ -575,10 +584,10 @@ VALUE LibevBackend_write_m(int argc, VALUE *argv, VALUE self) {
|
|
|
575
584
|
if (argc < 2)
|
|
576
585
|
// TODO: raise ArgumentError
|
|
577
586
|
rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
|
|
578
|
-
|
|
587
|
+
|
|
579
588
|
return (argc == 2) ?
|
|
580
589
|
LibevBackend_write(self, argv[0], argv[1]) :
|
|
581
|
-
LibevBackend_writev(self, argv[0], argc - 1, argv + 1);
|
|
590
|
+
LibevBackend_writev(self, argv[0], argc - 1, argv + 1);
|
|
582
591
|
}
|
|
583
592
|
|
|
584
593
|
///////////////////////////////////////////////////////////////////////////
|
|
@@ -604,13 +613,15 @@ VALUE LibevBackend_accept(VALUE self, VALUE sock) {
|
|
|
604
613
|
int e = errno;
|
|
605
614
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
606
615
|
|
|
607
|
-
switchpoint_result =
|
|
616
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_READ);
|
|
617
|
+
|
|
608
618
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
609
619
|
}
|
|
610
620
|
else {
|
|
611
621
|
VALUE socket;
|
|
612
622
|
rb_io_t *fp;
|
|
613
623
|
switchpoint_result = libev_snooze();
|
|
624
|
+
|
|
614
625
|
if (TEST_EXCEPTION(switchpoint_result)) {
|
|
615
626
|
close(fd); // close fd since we're raising an exception
|
|
616
627
|
goto error;
|
|
@@ -624,7 +635,7 @@ VALUE LibevBackend_accept(VALUE self, VALUE sock) {
|
|
|
624
635
|
rb_io_ascii8bit_binmode(socket);
|
|
625
636
|
io_set_nonblock(fp, socket);
|
|
626
637
|
rb_io_synchronized(fp);
|
|
627
|
-
|
|
638
|
+
|
|
628
639
|
// if (rsock_do_not_reverse_lookup) {
|
|
629
640
|
// fp->mode |= FMODE_NOREVLOOKUP;
|
|
630
641
|
// }
|
|
@@ -660,17 +671,19 @@ VALUE LibevBackend_accept_loop(VALUE self, VALUE sock) {
|
|
|
660
671
|
int e = errno;
|
|
661
672
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
662
673
|
|
|
663
|
-
switchpoint_result =
|
|
674
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_READ);
|
|
675
|
+
|
|
664
676
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
665
677
|
}
|
|
666
678
|
else {
|
|
667
679
|
rb_io_t *fp;
|
|
668
680
|
switchpoint_result = libev_snooze();
|
|
681
|
+
|
|
669
682
|
if (TEST_EXCEPTION(switchpoint_result)) {
|
|
670
683
|
close(fd); // close fd since we're raising an exception
|
|
671
684
|
goto error;
|
|
672
685
|
}
|
|
673
|
-
|
|
686
|
+
|
|
674
687
|
socket = rb_obj_alloc(cTCPSocket);
|
|
675
688
|
MakeOpenFile(socket, fp);
|
|
676
689
|
rb_update_max_fd(fd);
|
|
@@ -708,7 +721,7 @@ VALUE LibevBackend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
|
708
721
|
io_set_nonblock(fptr, sock);
|
|
709
722
|
watcher.fiber = Qnil;
|
|
710
723
|
|
|
711
|
-
addr.sin_family = AF_INET;
|
|
724
|
+
addr.sin_family = AF_INET;
|
|
712
725
|
addr.sin_addr.s_addr = inet_addr(host_buf);
|
|
713
726
|
addr.sin_port = htons(NUM2INT(port));
|
|
714
727
|
|
|
@@ -716,11 +729,14 @@ VALUE LibevBackend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
|
716
729
|
if (result < 0) {
|
|
717
730
|
int e = errno;
|
|
718
731
|
if (e != EINPROGRESS) rb_syserr_fail(e, strerror(e));
|
|
719
|
-
|
|
732
|
+
|
|
733
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
|
|
734
|
+
|
|
720
735
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
721
736
|
}
|
|
722
737
|
else {
|
|
723
738
|
switchpoint_result = libev_snooze();
|
|
739
|
+
|
|
724
740
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
725
741
|
}
|
|
726
742
|
RB_GC_GUARD(switchpoint_result);
|
|
@@ -729,21 +745,6 @@ error:
|
|
|
729
745
|
return RAISE_EXCEPTION(switchpoint_result);
|
|
730
746
|
}
|
|
731
747
|
|
|
732
|
-
VALUE libev_wait_fd(LibevBackend_t *backend, int fd, int events, int raise_exception) {
|
|
733
|
-
struct libev_io watcher;
|
|
734
|
-
VALUE switchpoint_result = Qnil;
|
|
735
|
-
|
|
736
|
-
watcher.fiber = rb_fiber_current();
|
|
737
|
-
ev_io_init(&watcher.io, LibevBackend_io_callback, fd, events);
|
|
738
|
-
ev_io_start(backend->ev_loop, &watcher.io);
|
|
739
|
-
switchpoint_result = libev_await(backend);
|
|
740
|
-
ev_io_stop(backend->ev_loop, &watcher.io);
|
|
741
|
-
|
|
742
|
-
if (raise_exception) TEST_RESUME_EXCEPTION(switchpoint_result);
|
|
743
|
-
RB_GC_GUARD(switchpoint_result);
|
|
744
|
-
return switchpoint_result;
|
|
745
|
-
}
|
|
746
|
-
|
|
747
748
|
VALUE LibevBackend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
748
749
|
LibevBackend_t *backend;
|
|
749
750
|
rb_io_t *fptr;
|
|
@@ -752,7 +753,7 @@ VALUE LibevBackend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
|
752
753
|
if (underlying_io != Qnil) io = underlying_io;
|
|
753
754
|
GetLibevBackend(self, backend);
|
|
754
755
|
GetOpenFile(io, fptr);
|
|
755
|
-
|
|
756
|
+
|
|
756
757
|
return libev_wait_fd(backend, fptr->fd, events, 1);
|
|
757
758
|
}
|
|
758
759
|
|
|
@@ -780,7 +781,6 @@ VALUE LibevBackend_sleep(VALUE self, VALUE duration) {
|
|
|
780
781
|
switchpoint_result = libev_await(backend);
|
|
781
782
|
|
|
782
783
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
|
783
|
-
|
|
784
784
|
TEST_RESUME_EXCEPTION(switchpoint_result);
|
|
785
785
|
RB_GC_GUARD(watcher.fiber);
|
|
786
786
|
RB_GC_GUARD(switchpoint_result);
|
|
@@ -811,10 +811,10 @@ VALUE LibevBackend_waitpid(VALUE self, VALUE pid) {
|
|
|
811
811
|
watcher.fiber = rb_fiber_current();
|
|
812
812
|
ev_child_init(&watcher.child, LibevBackend_child_callback, NUM2INT(pid), 0);
|
|
813
813
|
ev_child_start(backend->ev_loop, &watcher.child);
|
|
814
|
-
|
|
814
|
+
|
|
815
815
|
switchpoint_result = libev_await(backend);
|
|
816
|
-
ev_child_stop(backend->ev_loop, &watcher.child);
|
|
817
816
|
|
|
817
|
+
ev_child_stop(backend->ev_loop, &watcher.child);
|
|
818
818
|
TEST_RESUME_EXCEPTION(switchpoint_result);
|
|
819
819
|
RB_GC_GUARD(watcher.fiber);
|
|
820
820
|
RB_GC_GUARD(switchpoint_result);
|
|
@@ -838,9 +838,10 @@ VALUE LibevBackend_wait_event(VALUE self, VALUE raise) {
|
|
|
838
838
|
|
|
839
839
|
ev_async_init(&async, LibevBackend_async_callback);
|
|
840
840
|
ev_async_start(backend->ev_loop, &async);
|
|
841
|
+
|
|
841
842
|
switchpoint_result = libev_await(backend);
|
|
842
|
-
ev_async_stop(backend->ev_loop, &async);
|
|
843
843
|
|
|
844
|
+
ev_async_stop(backend->ev_loop, &async);
|
|
844
845
|
if (RTEST(raise)) TEST_RESUME_EXCEPTION(switchpoint_result);
|
|
845
846
|
RB_GC_GUARD(switchpoint_result);
|
|
846
847
|
return switchpoint_result;
|