polyphony 0.47.3 → 0.49.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/CHANGELOG.md +318 -295
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +40 -27
- data/examples/core/supervisor.rb +3 -3
- data/examples/core/worker-thread.rb +3 -4
- data/examples/io/tcp_proxy.rb +32 -0
- data/examples/io/unix_socket.rb +26 -0
- data/examples/performance/line_splitting.rb +34 -0
- data/examples/performance/loop.rb +32 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -0
- data/ext/polyphony/backend_common.h +2 -2
- data/ext/polyphony/backend_io_uring.c +42 -83
- data/ext/polyphony/backend_libev.c +32 -77
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +5 -4
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/thread.c +9 -28
- data/lib/polyphony.rb +1 -0
- data/lib/polyphony/adapters/postgres.rb +3 -3
- data/lib/polyphony/core/global_api.rb +14 -2
- data/lib/polyphony/core/thread_pool.rb +3 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +72 -0
- data/lib/polyphony/extensions/fiber.rb +32 -8
- data/lib/polyphony/extensions/io.rb +8 -14
- data/lib/polyphony/extensions/openssl.rb +4 -4
- data/lib/polyphony/extensions/socket.rb +68 -16
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +1 -0
- data/test/test_backend.rb +1 -1
- data/test/test_fiber.rb +64 -1
- data/test/test_global_api.rb +30 -0
- data/test/test_io.rb +26 -0
- data/test/test_socket.rb +32 -6
- data/test/test_supervise.rb +2 -1
- data/test/test_timer.rb +122 -0
- metadata +9 -4
- data/ext/polyphony/backend.h +0 -26
data/test/test_global_api.rb
CHANGED
@@ -307,6 +307,36 @@ class SpinLoopTest < MiniTest::Test
|
|
307
307
|
f.stop
|
308
308
|
assert_in_range 1..3, counter
|
309
309
|
end
|
310
|
+
|
311
|
+
def test_spin_loop_break
|
312
|
+
i = 0
|
313
|
+
f = spin_loop do
|
314
|
+
i += 1
|
315
|
+
snooze
|
316
|
+
break if i >= 5
|
317
|
+
end
|
318
|
+
f.await
|
319
|
+
assert_equal 5, i
|
320
|
+
|
321
|
+
i = 0
|
322
|
+
f = spin_loop do
|
323
|
+
i += 1
|
324
|
+
snooze
|
325
|
+
raise StopIteration if i >= 5
|
326
|
+
end
|
327
|
+
f.await
|
328
|
+
assert_equal 5, i
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_throttled_spin_loop_break
|
332
|
+
i = 0
|
333
|
+
f = spin_loop(rate: 100) do
|
334
|
+
i += 1
|
335
|
+
break if i >= 5
|
336
|
+
end
|
337
|
+
f.await
|
338
|
+
assert_equal 5, i
|
339
|
+
end
|
310
340
|
end
|
311
341
|
|
312
342
|
class SpinScopeTest < MiniTest::Test
|
data/test/test_io.rb
CHANGED
@@ -92,6 +92,32 @@ class IOTest < MiniTest::Test
|
|
92
92
|
assert_raises(EOFError) { i.readpartial(1) }
|
93
93
|
end
|
94
94
|
|
95
|
+
def test_gets
|
96
|
+
i, o = IO.pipe
|
97
|
+
|
98
|
+
buf = []
|
99
|
+
f = spin do
|
100
|
+
while (l = i.gets)
|
101
|
+
buf << l
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
snooze
|
106
|
+
assert_equal [], buf
|
107
|
+
|
108
|
+
o << 'fab'
|
109
|
+
snooze
|
110
|
+
assert_equal [], buf
|
111
|
+
|
112
|
+
o << "ulous\n"
|
113
|
+
10.times { snooze }
|
114
|
+
assert_equal ["fabulous\n"], buf
|
115
|
+
|
116
|
+
o.close
|
117
|
+
f.await
|
118
|
+
assert_equal ["fabulous\n"], buf
|
119
|
+
end
|
120
|
+
|
95
121
|
def test_getc
|
96
122
|
i, o = IO.pipe
|
97
123
|
|
data/test/test_socket.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'helper'
|
4
|
+
require 'fileutils'
|
4
5
|
|
5
6
|
class SocketTest < MiniTest::Test
|
6
7
|
def setup
|
@@ -24,7 +25,32 @@ class SocketTest < MiniTest::Test
|
|
24
25
|
snooze
|
25
26
|
client = TCPSocket.new('127.0.0.1', port)
|
26
27
|
client.write("1234\n")
|
27
|
-
assert_equal "1234\n", client.
|
28
|
+
assert_equal "1234\n", client.recv(8192)
|
29
|
+
client.close
|
30
|
+
ensure
|
31
|
+
server_fiber&.stop
|
32
|
+
server_fiber&.await
|
33
|
+
server&.close
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_unix_socket
|
37
|
+
path = '/tmp/test_unix_socket'
|
38
|
+
FileUtils.rm(path) rescue nil
|
39
|
+
server = UNIXServer.new(path)
|
40
|
+
server_fiber = spin do
|
41
|
+
server.accept_loop do |socket|
|
42
|
+
spin do
|
43
|
+
while (data = socket.gets(8192))
|
44
|
+
socket << data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
snooze
|
51
|
+
client = UNIXSocket.new(path)
|
52
|
+
client.write("1234\n")
|
53
|
+
assert_equal "1234\n", client.recv(8192)
|
28
54
|
client.close
|
29
55
|
ensure
|
30
56
|
server_fiber&.stop
|
@@ -34,18 +60,18 @@ class SocketTest < MiniTest::Test
|
|
34
60
|
end
|
35
61
|
|
36
62
|
class HTTPClientTest < MiniTest::Test
|
37
|
-
require 'httparty'
|
38
63
|
require 'json'
|
39
64
|
|
40
65
|
def test_http
|
41
|
-
res = HTTParty.get('http://
|
66
|
+
res = HTTParty.get('http://ipinfo.io/')
|
67
|
+
|
42
68
|
response = JSON.load(res.body)
|
43
|
-
assert_equal
|
69
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
44
70
|
end
|
45
71
|
|
46
72
|
def test_https
|
47
|
-
res = HTTParty.get('https://
|
73
|
+
res = HTTParty.get('https://ipinfo.io/')
|
48
74
|
response = JSON.load(res.body)
|
49
|
-
assert_equal
|
75
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
50
76
|
end
|
51
77
|
end
|
data/test/test_supervise.rb
CHANGED
data/test/test_timer.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
class TimerMoveOnAfterTest < MiniTest::Test
|
6
|
+
def setup
|
7
|
+
@timer = Polyphony::Timer.new(resolution: 0.01)
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@timer.stop
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_move_on_after
|
15
|
+
t0 = Time.now
|
16
|
+
v = @timer.move_on_after(0.1) do
|
17
|
+
sleep 1
|
18
|
+
:foo
|
19
|
+
end
|
20
|
+
t1 = Time.now
|
21
|
+
|
22
|
+
assert_in_range 0.1..0.15, t1 - t0
|
23
|
+
assert_nil v
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_move_on_after_with_value
|
27
|
+
t0 = Time.now
|
28
|
+
v = @timer.move_on_after(0.01, with_value: :bar) do
|
29
|
+
sleep 1
|
30
|
+
:foo
|
31
|
+
end
|
32
|
+
t1 = Time.now
|
33
|
+
|
34
|
+
assert_in_range 0.01..0.02, t1 - t0
|
35
|
+
assert_equal :bar, v
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_move_on_after_with_reset
|
39
|
+
t0 = Time.now
|
40
|
+
v = @timer.move_on_after(0.01, with_value: :moved_on) do
|
41
|
+
sleep 0.007
|
42
|
+
@timer.reset
|
43
|
+
sleep 0.007
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
t1 = Time.now
|
47
|
+
|
48
|
+
assert_nil v
|
49
|
+
assert_in_range 0.014..0.02, t1 - t0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class CancelAfterTest < MiniTest::Test
|
54
|
+
def setup
|
55
|
+
@timer = Polyphony::Timer.new(resolution: 0.01)
|
56
|
+
end
|
57
|
+
|
58
|
+
def teardown
|
59
|
+
@timer.stop
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_cancel_after
|
63
|
+
t0 = Time.now
|
64
|
+
|
65
|
+
assert_raises Polyphony::Cancel do
|
66
|
+
@timer.cancel_after(0.01) do
|
67
|
+
sleep 1
|
68
|
+
:foo
|
69
|
+
end
|
70
|
+
end
|
71
|
+
t1 = Time.now
|
72
|
+
assert_in_range 0.01..0.02, t1 - t0
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_cancel_after_with_reset
|
76
|
+
t0 = Time.now
|
77
|
+
@timer.cancel_after(0.01) do
|
78
|
+
sleep 0.007
|
79
|
+
@timer.reset
|
80
|
+
sleep 0.007
|
81
|
+
end
|
82
|
+
t1 = Time.now
|
83
|
+
assert_in_range 0.014..0.024, t1 - t0
|
84
|
+
end
|
85
|
+
|
86
|
+
class CustomException < Exception
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_cancel_after_with_custom_exception
|
90
|
+
assert_raises CustomException do
|
91
|
+
@timer.cancel_after(0.01, with_exception: CustomException) do
|
92
|
+
sleep 1
|
93
|
+
:foo
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
begin
|
98
|
+
err = nil
|
99
|
+
@timer.cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
|
100
|
+
sleep 1
|
101
|
+
:foo
|
102
|
+
end
|
103
|
+
rescue Exception => err
|
104
|
+
ensure
|
105
|
+
assert_kind_of CustomException, err
|
106
|
+
assert_equal 'custom message', err.message
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
begin
|
111
|
+
e = nil
|
112
|
+
@timer.cancel_after(0.01, with_exception: 'foo') do
|
113
|
+
sleep 1
|
114
|
+
:foo
|
115
|
+
end
|
116
|
+
rescue => e
|
117
|
+
ensure
|
118
|
+
assert_kind_of RuntimeError, e
|
119
|
+
assert_equal 'foo', e.message
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyphony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.49.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -269,7 +269,7 @@ dependencies:
|
|
269
269
|
- !ruby/object:Gem::Version
|
270
270
|
version: 0.3.0
|
271
271
|
description:
|
272
|
-
email:
|
272
|
+
email: sharon@noteflakes.com
|
273
273
|
executables: []
|
274
274
|
extensions:
|
275
275
|
- ext/polyphony/extconf.rb
|
@@ -383,13 +383,17 @@ files:
|
|
383
383
|
- examples/io/raw.rb
|
384
384
|
- examples/io/reline.rb
|
385
385
|
- examples/io/system.rb
|
386
|
+
- examples/io/tcp_proxy.rb
|
386
387
|
- examples/io/tcpserver.rb
|
387
388
|
- examples/io/tcpsocket.rb
|
388
389
|
- examples/io/tunnel.rb
|
390
|
+
- examples/io/unix_socket.rb
|
389
391
|
- examples/io/zip.rb
|
390
392
|
- examples/performance/fiber_resume.rb
|
391
393
|
- examples/performance/fiber_transfer.rb
|
392
394
|
- examples/performance/fs_read.rb
|
395
|
+
- examples/performance/line_splitting.rb
|
396
|
+
- examples/performance/loop.rb
|
393
397
|
- examples/performance/mem-usage.rb
|
394
398
|
- examples/performance/messaging.rb
|
395
399
|
- examples/performance/multi_snooze.rb
|
@@ -432,7 +436,6 @@ files:
|
|
432
436
|
- ext/liburing/setup.c
|
433
437
|
- ext/liburing/syscall.c
|
434
438
|
- ext/liburing/syscall.h
|
435
|
-
- ext/polyphony/backend.h
|
436
439
|
- ext/polyphony/backend_common.h
|
437
440
|
- ext/polyphony/backend_io_uring.c
|
438
441
|
- ext/polyphony/backend_io_uring_context.c
|
@@ -473,6 +476,7 @@ files:
|
|
473
476
|
- lib/polyphony/core/sync.rb
|
474
477
|
- lib/polyphony/core/thread_pool.rb
|
475
478
|
- lib/polyphony/core/throttler.rb
|
479
|
+
- lib/polyphony/core/timer.rb
|
476
480
|
- lib/polyphony/extensions/core.rb
|
477
481
|
- lib/polyphony/extensions/debug.rb
|
478
482
|
- lib/polyphony/extensions/fiber.rb
|
@@ -507,6 +511,7 @@ files:
|
|
507
511
|
- test/test_thread.rb
|
508
512
|
- test/test_thread_pool.rb
|
509
513
|
- test/test_throttler.rb
|
514
|
+
- test/test_timer.rb
|
510
515
|
- test/test_trace.rb
|
511
516
|
homepage: https://digital-fabric.github.io/polyphony
|
512
517
|
licenses:
|
data/ext/polyphony/backend.h
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
#ifndef BACKEND_H
|
2
|
-
#define BACKEND_H
|
3
|
-
|
4
|
-
#include "ruby.h"
|
5
|
-
|
6
|
-
typedef VALUE (* backend_pending_count_t)(VALUE self);
|
7
|
-
typedef VALUE (*backend_poll_t)(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
8
|
-
typedef VALUE (* backend_ref_t)(VALUE self);
|
9
|
-
typedef int (* backend_ref_count_t)(VALUE self);
|
10
|
-
typedef void (* backend_reset_ref_count_t)(VALUE self);
|
11
|
-
typedef VALUE (* backend_unref_t)(VALUE self);
|
12
|
-
typedef VALUE (* backend_wait_event_t)(VALUE self, VALUE raise_on_exception);
|
13
|
-
typedef VALUE (* backend_wakeup_t)(VALUE self);
|
14
|
-
|
15
|
-
typedef struct backend_interface {
|
16
|
-
backend_pending_count_t pending_count;
|
17
|
-
backend_poll_t poll;
|
18
|
-
backend_ref_t ref;
|
19
|
-
backend_ref_count_t ref_count;
|
20
|
-
backend_reset_ref_count_t reset_ref_count;
|
21
|
-
backend_unref_t unref;
|
22
|
-
backend_wait_event_t wait_event;
|
23
|
-
backend_wakeup_t wakeup;
|
24
|
-
} backend_interface_t;
|
25
|
-
|
26
|
-
#endif /* BACKEND_H */
|