polyphony 0.45.0 → 0.46.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 +2 -0
- data/.gitmodules +0 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile.lock +11 -3
- data/README.md +3 -3
- data/Rakefile +1 -1
- data/TODO.md +10 -18
- 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/raw.rb +14 -0
- data/examples/io/reline.rb +18 -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/performance/multi_snooze.rb +0 -1
- 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 -2
- data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
- data/examples/performance/thread_pool_perf.rb +6 -7
- data/ext/liburing/liburing.h +585 -0
- data/ext/liburing/liburing/README.md +4 -0
- data/ext/liburing/liburing/barrier.h +73 -0
- data/ext/liburing/liburing/compat.h +15 -0
- data/ext/liburing/liburing/io_uring.h +343 -0
- data/ext/liburing/queue.c +333 -0
- data/ext/liburing/register.c +187 -0
- data/ext/liburing/setup.c +210 -0
- data/ext/liburing/syscall.c +54 -0
- data/ext/liburing/syscall.h +18 -0
- data/ext/polyphony/backend.h +1 -16
- data/ext/polyphony/backend_common.h +109 -0
- data/ext/polyphony/backend_io_uring.c +884 -0
- data/ext/polyphony/backend_io_uring_context.c +73 -0
- data/ext/polyphony/backend_io_uring_context.h +52 -0
- data/ext/polyphony/{libev_backend.c → backend_libev.c} +255 -345
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +31 -13
- data/ext/polyphony/fiber.c +111 -27
- data/ext/polyphony/libev.c +4 -0
- data/ext/polyphony/libev.h +8 -2
- data/ext/polyphony/liburing.c +8 -0
- data/ext/polyphony/playground.c +51 -0
- data/ext/polyphony/polyphony.c +6 -8
- data/ext/polyphony/polyphony.h +29 -25
- data/ext/polyphony/polyphony_ext.c +13 -6
- data/ext/polyphony/queue.c +3 -4
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +102 -0
- data/ext/polyphony/runqueue_ring_buffer.c +85 -0
- data/ext/polyphony/runqueue_ring_buffer.h +31 -0
- data/ext/polyphony/thread.c +45 -92
- data/lib/polyphony.rb +2 -2
- data/lib/polyphony/adapters/fs.rb +1 -1
- data/lib/polyphony/adapters/process.rb +0 -3
- data/lib/polyphony/adapters/redis.rb +1 -1
- data/lib/polyphony/adapters/trace.rb +2 -2
- data/lib/polyphony/core/global_api.rb +9 -12
- data/lib/polyphony/core/sync.rb +6 -2
- data/lib/polyphony/extensions/core.rb +6 -24
- data/lib/polyphony/extensions/debug.rb +13 -0
- data/lib/polyphony/extensions/fiber.rb +21 -44
- data/lib/polyphony/extensions/io.rb +55 -10
- data/lib/polyphony/extensions/socket.rb +70 -12
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +3 -2
- data/test/helper.rb +36 -4
- data/test/io_uring_test.rb +55 -0
- data/test/stress.rb +5 -2
- data/test/test_backend.rb +4 -6
- data/test/test_ext.rb +1 -2
- data/test/test_fiber.rb +31 -24
- data/test/test_global_api.rb +58 -31
- data/test/test_io.rb +58 -0
- data/test/test_signal.rb +11 -8
- data/test/test_socket.rb +17 -0
- data/test/test_sync.rb +21 -0
- data/test/test_throttler.rb +3 -6
- data/test/test_trace.rb +7 -5
- metadata +86 -76
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 890abc2b84ed305f591c697764ea16255059aeb3cd4ddd23195b81f78f5f6daf
|
|
4
|
+
data.tar.gz: a02442318f82682ba1fa3a87e2b4e7ad8ae06d365a7d4a4b5c45689b2e55472f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 506a2fdbdee9e6c5bb94b976489537792941326080441f3d93924cd9657db5188b29e4ced6e1c8a6f8db06ae211da0522b3ac042e45365be1af2e68f8b157b0e
|
|
7
|
+
data.tar.gz: cbc0e333731e035c2094abfa72d425e649c210a8c9d3aec467446f615315cfc6e1f6de664321099ccdf93ddd6e1bb0ba484b2b8b53922725b2df8483aedefeab
|
data/.github/workflows/test.yml
CHANGED
data/.gitmodules
ADDED
|
File without changes
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
## 0.46.0
|
|
2
|
+
|
|
3
|
+
* Implement [io_uring backend](https://github.com/digital-fabric/polyphony/pull/44)
|
|
4
|
+
|
|
5
|
+
## 0.45.5
|
|
6
|
+
|
|
7
|
+
* Fix compilation error (#43)
|
|
8
|
+
* Add support for resetting move_on_after, cancel_after timeouts
|
|
9
|
+
* Optimize anti-event starvation polling
|
|
10
|
+
* Implement optimized runqueue for better performance
|
|
11
|
+
* Schedule parent with priority on uncaught exception
|
|
12
|
+
* Fix race condition in `Mutex#synchronize` (#41)
|
|
13
|
+
|
|
14
|
+
## 0.45.4
|
|
15
|
+
|
|
16
|
+
* Improve signal trapping mechanism
|
|
17
|
+
|
|
18
|
+
## 0.45.3
|
|
19
|
+
|
|
20
|
+
* Don't swallow error in `Process#kill_and_await`
|
|
21
|
+
* Add `Fiber#mailbox` attribute reader
|
|
22
|
+
* Fix bug in `Fiber.await`
|
|
23
|
+
* Implement `IO#getc`, `IO#getbyte`
|
|
24
|
+
|
|
25
|
+
## 0.45.2
|
|
26
|
+
|
|
27
|
+
* Rewrite `Fiber#<<`, `Fiber#await`, `Fiber#receive` in C
|
|
28
|
+
|
|
29
|
+
## 0.45.1
|
|
30
|
+
|
|
31
|
+
* Fix Net::HTTP compatibility
|
|
32
|
+
* Fix fs adapter
|
|
33
|
+
* Improve performance of IO#puts
|
|
34
|
+
* Mutex#synchronize
|
|
35
|
+
* Fix Socket#connect
|
|
36
|
+
* Cleanup code
|
|
37
|
+
* Improve support for Ruby 3 keyword args
|
|
38
|
+
|
|
1
39
|
## 0.45.0
|
|
2
40
|
|
|
3
41
|
* Cleanup code
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
polyphony (0.
|
|
4
|
+
polyphony (0.46.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -23,6 +23,9 @@ GEM
|
|
|
23
23
|
forwardable-extended (2.6.0)
|
|
24
24
|
hiredis (0.6.3)
|
|
25
25
|
http_parser.rb (0.6.0)
|
|
26
|
+
httparty (0.17.1)
|
|
27
|
+
mime-types (~> 3.0)
|
|
28
|
+
multi_xml (>= 0.5.2)
|
|
26
29
|
i18n (0.9.5)
|
|
27
30
|
concurrent-ruby (~> 1.0)
|
|
28
31
|
jekyll (3.8.6)
|
|
@@ -60,12 +63,16 @@ GEM
|
|
|
60
63
|
rb-inotify (~> 0.9, >= 0.9.10)
|
|
61
64
|
mercenary (0.3.6)
|
|
62
65
|
method_source (1.0.0)
|
|
66
|
+
mime-types (3.3.1)
|
|
67
|
+
mime-types-data (~> 3.2015)
|
|
68
|
+
mime-types-data (3.2020.0512)
|
|
63
69
|
minitest (5.13.0)
|
|
64
70
|
minitest-reporters (1.4.2)
|
|
65
71
|
ansi
|
|
66
72
|
builder
|
|
67
73
|
minitest (>= 5.0)
|
|
68
74
|
ruby-progressbar
|
|
75
|
+
multi_xml (0.6.0)
|
|
69
76
|
mysql2 (0.5.3)
|
|
70
77
|
parallel (1.19.1)
|
|
71
78
|
parser (2.7.0.2)
|
|
@@ -80,7 +87,7 @@ GEM
|
|
|
80
87
|
rack (2.2.3)
|
|
81
88
|
rainbow (3.0.0)
|
|
82
89
|
rake (12.3.3)
|
|
83
|
-
rake-compiler (1.
|
|
90
|
+
rake-compiler (1.1.1)
|
|
84
91
|
rake
|
|
85
92
|
rb-fsevent (0.10.3)
|
|
86
93
|
rb-inotify (0.10.1)
|
|
@@ -122,6 +129,7 @@ PLATFORMS
|
|
|
122
129
|
DEPENDENCIES
|
|
123
130
|
hiredis (= 0.6.3)
|
|
124
131
|
http_parser.rb (~> 0.6.0)
|
|
132
|
+
httparty (= 0.17.1)
|
|
125
133
|
jekyll (~> 3.8.6)
|
|
126
134
|
jekyll-remote-theme (~> 0.4.1)
|
|
127
135
|
jekyll-seo-tag (~> 2.6.1)
|
|
@@ -133,7 +141,7 @@ DEPENDENCIES
|
|
|
133
141
|
polyphony!
|
|
134
142
|
pry (= 0.13.1)
|
|
135
143
|
rack (>= 2.0.8, < 2.3.0)
|
|
136
|
-
rake-compiler (= 1.
|
|
144
|
+
rake-compiler (= 1.1.1)
|
|
137
145
|
redis (= 4.1.0)
|
|
138
146
|
rubocop (= 0.85.1)
|
|
139
147
|
sequel (= 5.34.0)
|
data/README.md
CHANGED
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
Polyphony is a library for building concurrent applications in Ruby. Polyphony
|
|
36
36
|
harnesses the power of [Ruby fibers](https://ruby-doc.org/core-2.5.1/Fiber.html)
|
|
37
37
|
to provide a cooperative, sequential coroutine-based concurrency model. Under
|
|
38
|
-
the hood, Polyphony uses
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
the hood, Polyphony uses
|
|
39
|
+
[io_uring](https://unixism.net/loti/what_is_io_uring.html) or
|
|
40
|
+
[libev](https://github.com/enki/libev) to maximize I/O performance.
|
|
41
41
|
|
|
42
42
|
## Features
|
|
43
43
|
|
data/Rakefile
CHANGED
|
@@ -23,4 +23,4 @@ task :docs do
|
|
|
23
23
|
exec 'RUBYOPT=-W0 jekyll serve -s docs -H ec2-18-156-117-172.eu-central-1.compute.amazonaws.com'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "**/*.jar", "pkg", "tmp"
|
|
26
|
+
CLEAN.include "**/*.o", "**/*.so", "**/*.so.*", "**/*.a", "**/*.bundle", "**/*.jar", "pkg", "tmp"
|
data/TODO.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
debugging). Focus on examples that serve as "how-to".
|
|
7
|
-
|
|
8
|
-
0.45.1
|
|
9
|
-
|
|
1
|
+
- change fiber_trace method to return nil, change trace logic to use provided
|
|
2
|
+
arguments instead of return values for fiber events
|
|
3
|
+
- allow backend selection at runtime
|
|
4
|
+
- add Backend#timer_loop that does what throttled_loop does, on lower level
|
|
5
|
+
- Adapter for io/console (what does `IO#raw` do?)
|
|
10
6
|
- Adapter for Pry and IRB (Which fixes #5 and #6)
|
|
7
|
+
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
|
8
|
+
inconsistent behaviour (see supervisor example).
|
|
9
|
+
- Fix backtrace for `Timeout.timeout` API (see timeout example).
|
|
10
|
+
- Check why worker-thread example doesn't work.
|
|
11
11
|
|
|
12
|
-
0.
|
|
12
|
+
0.47
|
|
13
13
|
|
|
14
14
|
- Debugging
|
|
15
15
|
- Eat your own dogfood: need a good tool to check what's going on when some
|
|
@@ -123,8 +123,6 @@
|
|
|
123
123
|
- discuss using `snooze` for ensuring responsiveness when executing CPU-bound work
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
## 0.47
|
|
127
|
-
|
|
128
126
|
### Some more API work, more docs
|
|
129
127
|
|
|
130
128
|
- sintra app with database access (postgresql)
|
|
@@ -136,14 +134,10 @@
|
|
|
136
134
|
- proceed from there
|
|
137
135
|
|
|
138
136
|
|
|
139
|
-
## 0.48
|
|
140
|
-
|
|
141
137
|
### Sinatra / Sidekiq
|
|
142
138
|
|
|
143
139
|
- Pull out redis/postgres code, put into new `polyphony-xxx` gems
|
|
144
140
|
|
|
145
|
-
## 0.49
|
|
146
|
-
|
|
147
141
|
### Testing && Docs
|
|
148
142
|
|
|
149
143
|
- More tests
|
|
@@ -154,8 +148,6 @@
|
|
|
154
148
|
- `IO.foreach`
|
|
155
149
|
- `Process.waitpid`
|
|
156
150
|
|
|
157
|
-
## 0.50 DNS
|
|
158
|
-
|
|
159
151
|
### DNS client
|
|
160
152
|
|
|
161
153
|
```ruby
|
|
@@ -6,7 +6,7 @@ require 'json'
|
|
|
6
6
|
|
|
7
7
|
X_SESSIONS = 1000
|
|
8
8
|
X_NODES = 10_000
|
|
9
|
-
X_SUBSCRIPTIONS_PER_SESSION =
|
|
9
|
+
X_SUBSCRIPTIONS_PER_SESSION = 1000
|
|
10
10
|
|
|
11
11
|
$sessions = []
|
|
12
12
|
X_SESSIONS.times do
|
|
@@ -17,8 +17,11 @@ X_SESSIONS.times do
|
|
|
17
17
|
}
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
REDIS_HOST = ENV['REDIS_HOST'] || 'localhost'
|
|
21
|
+
p redis_host: REDIS_HOST
|
|
22
|
+
|
|
20
23
|
spin do
|
|
21
|
-
redis = Redis.new
|
|
24
|
+
redis = Redis.new(host: REDIS_HOST)
|
|
22
25
|
redis.subscribe('events') do |on|
|
|
23
26
|
on.message do |_, message|
|
|
24
27
|
distribute_event(JSON.parse(message, symbolize_names: true))
|
|
@@ -30,18 +33,18 @@ $update_count = 0
|
|
|
30
33
|
|
|
31
34
|
def distribute_event(event)
|
|
32
35
|
$update_count += 1
|
|
33
|
-
|
|
36
|
+
t0 = Time.now
|
|
34
37
|
count = 0
|
|
35
38
|
$sessions.each do |s|
|
|
36
39
|
count += 1 if s[:subscriptions].include?(event[:path])
|
|
37
40
|
end
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
elapsed = Time.now - t0
|
|
42
|
+
rate = X_SESSIONS / elapsed
|
|
43
|
+
puts "elapsed: #{elapsed} (#{rate}/s)" if $update_count % 100 == 0
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
spin do
|
|
44
|
-
redis = Redis.new
|
|
47
|
+
redis = Redis.new(host: REDIS_HOST)
|
|
45
48
|
throttled_loop(1000) do
|
|
46
49
|
redis.publish('events', { path: "node#{rand(X_NODES)}" }.to_json)
|
|
47
50
|
end
|
|
@@ -60,7 +63,7 @@ spin do
|
|
|
60
63
|
end
|
|
61
64
|
end
|
|
62
65
|
|
|
63
|
-
trap(
|
|
66
|
+
trap('SIGINT') do
|
|
64
67
|
puts 'bye...'
|
|
65
68
|
exit!
|
|
66
69
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony/adapters/sequel'
|
|
5
|
+
require 'polyphony/adapters/postgres'
|
|
6
|
+
|
|
7
|
+
URL = ENV['SEQUEL_URL'] || 'postgres://localhost/test'
|
|
8
|
+
|
|
9
|
+
x = 10000
|
|
10
|
+
query_count = 0
|
|
11
|
+
|
|
12
|
+
spin do
|
|
13
|
+
db = Sequel.connect(URL)
|
|
14
|
+
x.times { query_count += 1; db.execute('select 1 as test') }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
spin do
|
|
18
|
+
db = Sequel.connect(URL)
|
|
19
|
+
x.times { query_count += 1; db.execute('select 2 as test') }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
t0 = Time.now
|
|
23
|
+
Fiber.current.await_all_children
|
|
24
|
+
puts "query rate: #{query_count / (Time.now - t0)} reqs/s; count = #{query_count}"
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'polyphony'
|
|
5
|
+
|
|
6
|
+
spin do
|
|
7
|
+
puts 'two'
|
|
8
|
+
# spinning a fiber from the parent fiber allows us to schedule an operation to
|
|
9
|
+
# be performed even after the current fiber is terminated
|
|
10
|
+
Fiber.current.parent.spin { puts 'four' }
|
|
11
|
+
puts 'three'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
puts 'one'
|
|
15
|
+
|
|
16
|
+
suspend
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
require 'bundler/setup'
|
|
4
4
|
require 'polyphony'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
module GenServer
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def start(receiver, *args)
|
|
8
10
|
fiber = spin do
|
|
9
11
|
state = receiver.initial_state(*args)
|
|
10
12
|
loop do
|
|
@@ -14,11 +16,10 @@ class GenServer
|
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
build_api(fiber, receiver)
|
|
17
|
-
snooze
|
|
18
19
|
fiber
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def
|
|
22
|
+
def build_api(fiber, receiver)
|
|
22
23
|
receiver.methods(false).each do |m|
|
|
23
24
|
if m =~ /!$/
|
|
24
25
|
fiber.define_singleton_method(m) do |*args|
|
|
@@ -32,7 +33,7 @@ class GenServer
|
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
35
|
-
def
|
|
36
|
+
def cast(process, method, *args)
|
|
36
37
|
process << {
|
|
37
38
|
from: Fiber.current,
|
|
38
39
|
method: method,
|
|
@@ -40,7 +41,7 @@ class GenServer
|
|
|
40
41
|
}
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
def
|
|
44
|
+
def call(process, method, *args)
|
|
44
45
|
process << {
|
|
45
46
|
from: Fiber.current,
|
|
46
47
|
method: method,
|
|
@@ -50,21 +51,27 @@ class GenServer
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
|
|
54
|
+
# In a generic server the state is not held in an instance variable but rather
|
|
55
|
+
# passed as the first parameter to method calls. The return value of each method
|
|
56
|
+
# is an array consisting of the result and the potentially mutated state.
|
|
53
57
|
module Map
|
|
54
|
-
|
|
58
|
+
module_function
|
|
59
|
+
|
|
60
|
+
def initial_state(hash = {})
|
|
55
61
|
hash
|
|
56
62
|
end
|
|
57
63
|
|
|
58
|
-
def
|
|
64
|
+
def get(state, key)
|
|
59
65
|
[state[key], state]
|
|
60
66
|
end
|
|
61
67
|
|
|
62
|
-
def
|
|
68
|
+
def put!(state, key, value)
|
|
63
69
|
state[key] = value
|
|
64
70
|
[:noreply, state]
|
|
65
71
|
end
|
|
66
72
|
end
|
|
67
73
|
|
|
74
|
+
# start server with initial state
|
|
68
75
|
map_server = GenServer.start(Map, {foo: :bar})
|
|
69
76
|
|
|
70
77
|
puts 'getting value from map server'
|
|
File without changes
|
|
@@ -9,10 +9,12 @@ pong = spin_loop do
|
|
|
9
9
|
ping << 'pong'
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
ping =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
ping = spin do
|
|
13
|
+
3.times do
|
|
14
|
+
pong << ['ping', Fiber.current]
|
|
15
|
+
msg = receive
|
|
16
|
+
puts msg
|
|
17
|
+
end
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
ping.await
|