polyphony 0.29 → 0.30
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/.gitignore +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +15 -10
- data/docs/getting-started/tutorial.md +3 -3
- data/docs/index.md +2 -3
- data/docs/{technical-overview → main-concepts}/concurrency.md +62 -15
- data/docs/{technical-overview → main-concepts}/design-principles.md +21 -8
- data/docs/{technical-overview → main-concepts}/exception-handling.md +80 -38
- data/docs/{technical-overview → main-concepts}/extending.md +4 -3
- data/docs/{technical-overview → main-concepts}/fiber-scheduling.md +3 -3
- data/docs/{technical-overview.md → main-concepts.md} +2 -2
- data/examples/core/xx-at_exit.rb +29 -0
- data/examples/core/xx-fork-terminate.rb +27 -0
- data/examples/core/xx-pingpong.rb +18 -0
- data/examples/core/xx-stop.rb +20 -0
- data/ext/gyro/async.c +1 -1
- data/ext/gyro/extconf.rb +0 -3
- data/ext/gyro/gyro.c +7 -8
- data/ext/gyro/gyro.h +2 -0
- data/ext/gyro/queue.c +6 -6
- data/ext/gyro/selector.c +32 -1
- data/ext/gyro/thread.c +55 -9
- data/ext/gyro/timer.c +1 -0
- data/lib/polyphony/core/exceptions.rb +4 -1
- data/lib/polyphony/core/global_api.rb +1 -6
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/extensions/core.rb +7 -1
- data/lib/polyphony/extensions/fiber.rb +159 -72
- data/lib/polyphony/extensions/io.rb +2 -4
- data/lib/polyphony/extensions/openssl.rb +0 -17
- data/lib/polyphony/extensions/thread.rb +46 -22
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +20 -18
- data/test/coverage.rb +1 -1
- data/test/helper.rb +7 -3
- data/test/test_fiber.rb +285 -72
- data/test/test_global_api.rb +7 -52
- data/test/test_io.rb +8 -0
- data/test/test_signal.rb +1 -0
- data/test/test_thread.rb +76 -56
- data/test/test_thread_pool.rb +27 -5
- data/test/test_throttler.rb +1 -0
- metadata +12 -12
- data/lib/polyphony/core/supervisor.rb +0 -114
- data/lib/polyphony/line_reader.rb +0 -82
- data/test/test_gyro.rb +0 -25
- data/test/test_supervisor.rb +0 -180
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf1cef97b80aa22506d7b5d1547062cfb62909ef12411fe0877ff3972f00198f
|
4
|
+
data.tar.gz: 5418b1912ea214600fbbc435e91f56e6db325dd21710530932fef944b27fc7ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f878c45416276bb13e40c8641ab614d75c47f82b82859ab21fa37ae7012e487d040919b50a8f588d097fa2ab95295f20b79a91ab5ae4ec8177f0846c6cbd3892
|
7
|
+
data.tar.gz: 9d97c148ea0f54e15d1c55209a53131d09278fa7c8dd426c1f3d945ba26f86c0ffebb056dde9f4e324719a3dc424afcde2bbf99cddbadfe781bc9e1fab965ef9
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
0.30 2020-14-02
|
2
|
+
---------------
|
3
|
+
|
4
|
+
* Add support for awaiting a fiber from multiple monitor fibers at once
|
5
|
+
* Implemented child fibers
|
6
|
+
* Fix TERM and INT signal handling (close #11)
|
7
|
+
* Fix compiling on Linux
|
8
|
+
* Do not reset runnable value in Gyro_suspend (prevents interrupting timers)
|
9
|
+
* Don't snooze when stopping a fiber
|
10
|
+
* Fix IO#read for files larger than 8KB (#10)
|
11
|
+
* Fix fiber messaging in main fiber
|
12
|
+
* Prevent signalling of inactive async watcher
|
13
|
+
* Better fiber messaging
|
14
|
+
|
1
15
|
0.29 2020-02-02
|
2
16
|
---------------
|
3
17
|
|
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
@@ -1,15 +1,20 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.31 Working Sinatra application
|
2
|
+
|
3
|
+
- Accept rate/interval in `spin_loop` and `spin_worker_loop`:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
spin_loop(10) { ... } # 10 times per second
|
7
|
+
spin_loop(rate: 10) { ... } # 10 times per second
|
8
|
+
spin_loop(interval: 10) { ... } # once every ten seconds
|
9
|
+
```
|
2
10
|
|
3
11
|
- Docs: explain difference between `sleep` and `suspend`
|
4
12
|
- Check why first call to `#sleep` returns too early in tests. Check the
|
5
13
|
sleep behaviour in a spawned thread.
|
6
|
-
|
7
|
-
## 0.30 Working Sinatra application
|
8
|
-
|
9
14
|
- app with database access (postgresql)
|
10
15
|
- benchmarks!
|
11
16
|
|
12
|
-
## 0.
|
17
|
+
## 0.32 Sidekick
|
13
18
|
|
14
19
|
Plan of action:
|
15
20
|
|
@@ -17,13 +22,13 @@ Plan of action:
|
|
17
22
|
- test performance
|
18
23
|
- proceed from there
|
19
24
|
|
20
|
-
## 0.
|
25
|
+
## 0.33 Testing && Docs
|
21
26
|
|
22
27
|
- Pull out redis/postgres code, put into new `polyphony-xxx` gems
|
23
28
|
|
24
|
-
## 0.
|
29
|
+
## 0.34 Integration
|
25
30
|
|
26
|
-
## 0.
|
31
|
+
## 0.35 Real IO#gets and IO#read
|
27
32
|
|
28
33
|
- More tests
|
29
34
|
- Implement some basic stuff missing:
|
@@ -33,11 +38,11 @@ Plan of action:
|
|
33
38
|
- `IO.foreach`
|
34
39
|
- `Process.waitpid`
|
35
40
|
|
36
|
-
## 0.
|
41
|
+
## 0.36 Rails
|
37
42
|
|
38
43
|
- Rails?
|
39
44
|
|
40
|
-
## 0.
|
45
|
+
## 0.37 DNS
|
41
46
|
|
42
47
|
### DNS client
|
43
48
|
|
@@ -5,7 +5,7 @@ nav_order: 2
|
|
5
5
|
parent: Getting Started
|
6
6
|
permalink: /getting-started/tutorial/
|
7
7
|
prev_title: Installing Polyphony
|
8
|
-
next_title:
|
8
|
+
next_title: Concurrency the Easy Way
|
9
9
|
---
|
10
10
|
# A Gentle Introduction to Polyphony
|
11
11
|
|
@@ -332,7 +332,7 @@ fiber.raise 'foo'
|
|
332
332
|
```
|
333
333
|
|
334
334
|
For more information on how exceptions are handled in Polyphony, see [exception
|
335
|
-
handling](../../
|
335
|
+
handling](../../main-concepts/exception-handling/).
|
336
336
|
|
337
337
|
## Supervising - controlling multiple fibers at once
|
338
338
|
|
@@ -441,6 +441,6 @@ possibilities for Ruby. Polyphony has the performance characteristics and
|
|
441
441
|
provides the necessary tools for transforming how concurrent Ruby apps are
|
442
442
|
written. Polyphony is still new, and the present documentation is far from being
|
443
443
|
complete. To learn more about Polyphony, read the [technical
|
444
|
-
overview](../../
|
444
|
+
overview](../../main-concepts/design-principles/). For more examples please
|
445
445
|
consult the [Github
|
446
446
|
repository](https://github.com/digital-fabric/polyphony/tree/master/examples).
|
data/docs/index.md
CHANGED
@@ -78,10 +78,9 @@ Polyphony draws inspiration from the following, in no particular order:
|
|
78
78
|
|
79
79
|
## Going further
|
80
80
|
|
81
|
-
To learn more about using Polyphony to build concurrent applications,
|
82
|
-
technical overview below, or look at the [included
|
81
|
+
To learn more about using Polyphony to build concurrent applications, continue reading, or look at the [bundled
|
83
82
|
examples](https://github.com/digital-fabric/polyphony/tree/9e0f3b09213156bdf376ef33684ef267517f06e8/examples/README.md).
|
84
|
-
A thorough reference is forthcoming.
|
83
|
+
A thorough API reference is forthcoming.
|
85
84
|
|
86
85
|
## Contributing to Polyphony
|
87
86
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
3
|
title: Concurrency the Easy Way
|
4
|
-
nav_order:
|
5
|
-
parent:
|
6
|
-
permalink: /
|
7
|
-
prev_title:
|
4
|
+
nav_order: 1
|
5
|
+
parent: Main Concepts
|
6
|
+
permalink: /main-concepts/concurrency/
|
7
|
+
prev_title: A Gentle Introduction to Polyphony
|
8
8
|
next_title: How Fibers are Scheduled
|
9
9
|
---
|
10
10
|
# Concurrency the Easy Way
|
@@ -65,10 +65,64 @@ understand, compared to callback-style programming.
|
|
65
65
|
|
66
66
|
Polyphony extends the core `Fiber` class with additional functionality that
|
67
67
|
allows scheduling, synchronizing, interrupting and otherwise controlling running
|
68
|
-
fibers.
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
fibers. Starting a concurrent operation inside a fiber is as simple as a `spin`
|
69
|
+
method call:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
while (connection = server.accept)
|
73
|
+
spin { handle_connection(connection) }
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
In order to facilitate developing applications that employ complex concurrent
|
78
|
+
patterns and can scale easily, Polyphony employs a [structured
|
79
|
+
approach](https://en.wikipedia.org/wiki/Structured_concurrency) to controlling
|
80
|
+
fiber lifetime. A spun fiber is considered the *child* of the fiber from which
|
81
|
+
it was spun, and is always limited to the life time of its parent:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
parent = spin do
|
85
|
+
do_something
|
86
|
+
child = spin do
|
87
|
+
do_some_other_stuff
|
88
|
+
end
|
89
|
+
# the child fiber is guaranteed to stop executing before the parent fiber
|
90
|
+
# terminates
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
Any uncaught exception raised in a fiber will be
|
95
|
+
[propagated]((exception-handling.md)) to its parent, and potentially further up
|
96
|
+
the fiber hierarchy, all the way to the main fiber:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
parent = spin do
|
100
|
+
child = spin do
|
101
|
+
raise 'foo'
|
102
|
+
end
|
103
|
+
sleep
|
104
|
+
end
|
105
|
+
|
106
|
+
sleep
|
107
|
+
# the exception will be propagated from the child fiber to the parent fiber,
|
108
|
+
# and from the parent fiber to the main fiber, which will cause the program to
|
109
|
+
# abort.
|
110
|
+
```
|
111
|
+
|
112
|
+
In addition, fibers can communicate with each other using message passing,
|
113
|
+
turning them into autonomous actors in a highly concurrent environment. Message
|
114
|
+
passing is in many ways a superior way to pass data between concurrent entities,
|
115
|
+
obviating the need to synchronize access to shared resources:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
writer = spin do
|
119
|
+
while (write_request = receive)
|
120
|
+
do_write(write_request)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
...
|
124
|
+
writer << { stamp: Time.now, value: rand }
|
125
|
+
```
|
72
126
|
|
73
127
|
## Higher-Order Concurrency Constructs
|
74
128
|
|
@@ -80,19 +134,13 @@ Cancel scopes \(borrowed from the brilliant Python library
|
|
80
134
|
[Trio](https://trio.readthedocs.io/en/stable/)\) allows cancelling ongoing
|
81
135
|
operations for any reason with more control over cancelling behaviour.
|
82
136
|
|
83
|
-
Supervisors allow controlling multiple fibers. They offer enhanced exception
|
84
|
-
handling and can be nested to create complex supervision trees ala
|
85
|
-
[Erlang](https://adoptingerlang.org/docs/development/supervision_trees/).
|
86
|
-
|
87
137
|
Some other constructs offered by Polyphony:
|
88
138
|
|
89
139
|
* `Mutex` - a mutex used to synchronize access to a single shared resource.
|
90
140
|
* `ResourcePool` - used for synchronizing access to a limited amount of shared
|
91
|
-
|
92
141
|
resources, for example a pool of database connections.
|
93
142
|
|
94
143
|
* `Throttler` - used for throttling repeating operations, for example throttling
|
95
|
-
|
96
144
|
access to a shared resource, or throttling incoming requests.
|
97
145
|
|
98
146
|
## A Compelling Concurrency Solution for Ruby
|
@@ -106,4 +154,3 @@ way to write concurrent applications in Ruby. Polyphony aims to show that Ruby
|
|
106
154
|
can be used for developing sufficiently high-performance applications, while
|
107
155
|
offering all the advantages of Ruby, with source code that is easy to read and
|
108
156
|
understand.
|
109
|
-
|
@@ -1,16 +1,26 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
3
|
title: Design Principles
|
4
|
-
nav_order:
|
5
|
-
parent:
|
6
|
-
permalink: /
|
7
|
-
prev_title:
|
8
|
-
next_title: Concurrency the Easy Way
|
4
|
+
nav_order: 5
|
5
|
+
parent: Main Concepts
|
6
|
+
permalink: /main-concepts/design-principles/
|
7
|
+
prev_title: Extending Polyphony
|
9
8
|
---
|
10
9
|
# Design Principles
|
11
10
|
|
12
|
-
Polyphony was created in order to enable
|
13
|
-
applications in Ruby,
|
11
|
+
Polyphony was created in order to enable developing high-performance concurrent
|
12
|
+
applications in Ruby using a fluent, compact syntax and API. Polyphony enables
|
13
|
+
fine-grained concurrency - the splitting up of operations into a large number of
|
14
|
+
concurrent tasks, each concerned with small part of the whole and advancing at
|
15
|
+
its own pace.
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
a single Ruby process may spin up millions of
|
21
|
+
concurrent fibers.
|
22
|
+
|
23
|
+
, by utilizing Ruby fibers together with the
|
14
24
|
[libev](http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod) event reactor
|
15
25
|
library. Polyphony's design is based on the following principles:
|
16
26
|
|
@@ -57,8 +67,11 @@ library. Polyphony's design is based on the following principles:
|
|
57
67
|
}
|
58
68
|
```
|
59
69
|
|
70
|
+
- Breaking up operations into
|
71
|
+
|
60
72
|
- Polyphony should embrace Ruby's standard `raise/rescue/ensure` exception
|
61
|
-
handling mechanism
|
73
|
+
handling mechanism. Exception handling in a highly concurrent environment
|
74
|
+
should be robust and foolproof:
|
62
75
|
|
63
76
|
```ruby
|
64
77
|
cancel_after(0.5) do
|
@@ -1,21 +1,21 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
3
|
title: Exception Handling
|
4
|
-
nav_order:
|
5
|
-
parent:
|
6
|
-
permalink: /
|
4
|
+
nav_order: 3
|
5
|
+
parent: Main Concepts
|
6
|
+
permalink: /main-concepts/exception-handling/
|
7
7
|
prev_title: How Fibers are Scheduled
|
8
8
|
next_title: Extending Polyphony
|
9
9
|
---
|
10
10
|
# Exception Handling
|
11
11
|
|
12
12
|
Ruby employs a pretty robust exception handling mechanism. An raised exception
|
13
|
-
will
|
14
|
-
on the exception's class. In addition, the exception will include a stack
|
15
|
-
showing the execution path from the exception's locus back to the
|
16
|
-
entry point. Unfortunately, when exceptions are raised while switching
|
17
|
-
fibers, stack traces will only include partial information. Here's a
|
18
|
-
demonstration:
|
13
|
+
will propagate up the fiber tree until a suitable exception handler is found,
|
14
|
+
based on the exception's class. In addition, the exception will include a stack
|
15
|
+
trace showing the execution path from the exception's locus back to the
|
16
|
+
program's entry point. Unfortunately, when exceptions are raised while switching
|
17
|
+
between fibers, stack traces will only include partial information. Here's a
|
18
|
+
simple demonstration:
|
19
19
|
|
20
20
|
_fiber\_exception.rb_
|
21
21
|
|
@@ -124,7 +124,7 @@ fired or not. We call `timer.stop` inside an ensure block, thus ensuring that
|
|
124
124
|
the timer will have stopped once the awaiting fiber has resumed, even if it has
|
125
125
|
not fired.
|
126
126
|
|
127
|
-
##
|
127
|
+
## Exception Propagation
|
128
128
|
|
129
129
|
One of the "annoying" things about exceptions is that for them to be useful, you
|
130
130
|
have to intercept them \(using `rescue`\). If you forget to do that, you'll end
|
@@ -132,9 +132,9 @@ up with uncaught exceptions that can wreak havoc. For example, by default a Ruby
|
|
132
132
|
`Thread` in which an exception was raised without being caught, will simply
|
133
133
|
terminate with the exception silently swallowed.
|
134
134
|
|
135
|
-
To prevent the same from happening with fibers, Polyphony provides a
|
136
|
-
that
|
137
|
-
Let's discuss the following example:
|
135
|
+
To prevent the same from happening with fibers, Polyphony provides a robust
|
136
|
+
mechanism that propagates uncaught exceptions up through the chain of parent
|
137
|
+
fibers. Let's discuss the following example:
|
138
138
|
|
139
139
|
```ruby
|
140
140
|
require 'polyphony'
|
@@ -144,17 +144,23 @@ spin do
|
|
144
144
|
spin do
|
145
145
|
spin do
|
146
146
|
raise 'foo'
|
147
|
-
end
|
148
|
-
|
149
|
-
|
150
|
-
|
147
|
+
end
|
148
|
+
sleep
|
149
|
+
end
|
150
|
+
sleep
|
151
|
+
end
|
152
|
+
sleep
|
153
|
+
end
|
154
|
+
|
155
|
+
sleep
|
151
156
|
```
|
152
157
|
|
153
|
-
In
|
154
|
-
|
155
|
-
|
158
|
+
In the above example, four nested fibers are created, and each of them, except
|
159
|
+
for the innermost fiber, goes to sleep for an unlimited duration. An exception
|
160
|
+
is raised in the innermost fiber, and having no corresponding exception handler,
|
161
|
+
will propagate up through the enclosing fibers, until reaching the
|
156
162
|
top-most level, that of the root fiber, at which point the exception will cause
|
157
|
-
the program to
|
163
|
+
the program to abort and print an error message.
|
158
164
|
|
159
165
|
## MoveOn and Cancel - Interrupting Fiber Execution
|
160
166
|
|
@@ -163,8 +169,8 @@ provides two exception classes that used exclusively to interrupt fiber
|
|
163
169
|
execution: `MoveOn` and `Cancel`. Both of these classes are used in various
|
164
170
|
fiber-control APIs, and `MoveOn` exceptions in particular are handled in a
|
165
171
|
particular manner by Polyphony. The difference between `MoveOn` and `Cancel` is
|
166
|
-
that `MoveOn` stops fiber execution without the exception
|
167
|
-
optionally provide an arbitrary return value for the fiber. `Cancel` will
|
172
|
+
that `MoveOn` stops fiber execution without the exception propagating. It can
|
173
|
+
optionally provide an arbitrary return value for the fiber. `Cancel` will propagate
|
168
174
|
up like all exceptions.
|
169
175
|
|
170
176
|
The `MoveOn` and `Cancel` classes are normally used indirectly, through the
|
@@ -183,22 +189,58 @@ f3 = spin { sleep 100 }
|
|
183
189
|
f3.cancel #=> will raise a Cancel exception
|
184
190
|
```
|
185
191
|
|
186
|
-
|
192
|
+
In addition to `MoveOn` and `Cancel`, Polyphony employs internally another
|
193
|
+
exception class, `Terminate` for terminating a fiber once its parent has
|
194
|
+
finished executing.
|
195
|
+
|
196
|
+
## The Special Problem of Signal Handling
|
197
|
+
|
198
|
+
Ruby by default handles process signals by generating exceptions, allowing the
|
199
|
+
handling of signals in a structured manner. However, process signals may arrive
|
200
|
+
at any moment, and may be trapped while any arbitrary fiber is running, and even
|
201
|
+
while an event loop is running.
|
187
202
|
|
188
|
-
|
189
|
-
|
190
|
-
|
203
|
+
Two signals in particular require special care as they involve the stopping of
|
204
|
+
the entire process: `TERM` and `INT`. The `TERM` signal should be handled
|
205
|
+
gracefully, i.e. with proper cleanup, which also means terminating all fibers.
|
206
|
+
The `INT` signal requires halting the process and printing a correct stack
|
207
|
+
trace.
|
208
|
+
|
209
|
+
To ensure correct behaviour for these two signals, polyphony installs signal
|
210
|
+
handlers that ensure that the main thread's event loop stops if it's currently
|
211
|
+
running, and that the corresponding exceptions (namely `SystemExit` and
|
212
|
+
`Interrupt`) are handled correctly by propagating them using Polyphony's normal
|
213
|
+
exception handling mechanisms.
|
214
|
+
|
215
|
+
Care should be taken when handling other signals. There are two options for
|
216
|
+
correctly handling the signals: using Ruby's stock `trap` method, and using
|
217
|
+
Polyphony's signal watchers. The stock method involves trapping signals as
|
218
|
+
usual, but making sure we're not inside the event loop:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
trap('SIGHUP') do
|
222
|
+
Thread.current.break_out_of_ev_loop(nil)
|
223
|
+
handle_hup_signal
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
The alternative is to use `Polyphony.wait_for_signal`:
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
hup_handler = spin_loop do
|
231
|
+
Polyphony.wait_for_signal
|
232
|
+
handle_hup_signal
|
233
|
+
end
|
234
|
+
```
|
191
235
|
|
192
|
-
|
193
|
-
and process termination: `Interrupt` - raised upon receiving an `INT` signal;
|
194
|
-
`SystemExit` - raised upon calling `Kernel#exit`; and `SignalException` - raised
|
195
|
-
upon receiving other signals.
|
236
|
+
## The Special Problem of Thread Termination
|
196
237
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
238
|
+
Thread termination using `Thread#kill` or `Thread#raise` also presents the same
|
239
|
+
problems as signal handling in a multi-fiber environment. The termination can
|
240
|
+
occur while any fiber is running, and even while running the thread's event
|
241
|
+
loop.
|
201
242
|
|
202
|
-
|
203
|
-
|
204
|
-
|
243
|
+
To ensure proper thread termination, including the termination of all the
|
244
|
+
thread's fibers, Polyphony patches the `Thread#kill` and `Thread#raise` methods
|
245
|
+
to schedule the thread's main fiber with the corresponding exceptions, thus
|
246
|
+
ensuring an orderly termination or exception handling.
|
@@ -1,10 +1,11 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
3
|
title: Extending Polyphony
|
4
|
-
nav_order:
|
5
|
-
parent:
|
6
|
-
permalink: /
|
4
|
+
nav_order: 4
|
5
|
+
parent: Main Concepts
|
6
|
+
permalink: /main-concepts/extending/
|
7
7
|
prev_title: Exception Handling
|
8
|
+
next_title: Design Principles
|
8
9
|
---
|
9
10
|
# Extending Polyphony
|
10
11
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
3
|
title: How Fibers are Scheduled
|
4
|
-
nav_order:
|
5
|
-
parent:
|
6
|
-
permalink: /
|
4
|
+
nav_order: 2
|
5
|
+
parent: Main Concepts
|
6
|
+
permalink: /main-concepts/fiber-scheduling/
|
7
7
|
prev_title: Concurrency the Easy Way
|
8
8
|
next_title: Exception Handling
|
9
9
|
---
|
@@ -1,10 +1,10 @@
|
|
1
1
|
---
|
2
2
|
layout: page
|
3
|
-
title:
|
3
|
+
title: Main Concepts
|
4
4
|
description: Lorem ipsum
|
5
5
|
has_children: true
|
6
6
|
section: true
|
7
7
|
has_toc: false
|
8
8
|
nav_order: 3
|
9
|
-
section_link: /
|
9
|
+
section_link: /main-concepts/concurrency
|
10
10
|
---
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
Exception.__disable_sanitized_backtrace__ = true
|
7
|
+
|
8
|
+
child_pid = Polyphony.fork do
|
9
|
+
at_exit do
|
10
|
+
puts "at_exit"
|
11
|
+
f = spin { sleep 10 }
|
12
|
+
trap('SIGINT') { f.stop }
|
13
|
+
f.await
|
14
|
+
end
|
15
|
+
|
16
|
+
f1 = spin { sleep 100 }
|
17
|
+
|
18
|
+
puts "pid: #{Process.pid}"
|
19
|
+
|
20
|
+
pid = Process.pid
|
21
|
+
|
22
|
+
f1.join
|
23
|
+
end
|
24
|
+
|
25
|
+
sleep 0.1
|
26
|
+
Process.kill('INT', child_pid)
|
27
|
+
sleep 0.1
|
28
|
+
Process.kill('INT', child_pid)
|
29
|
+
Process.wait(child_pid)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
Exception.__disable_sanitized_backtrace__ = true
|
7
|
+
|
8
|
+
pid = Polyphony.fork do
|
9
|
+
f = spin do
|
10
|
+
p 1
|
11
|
+
sleep 1
|
12
|
+
p 2
|
13
|
+
ensure
|
14
|
+
p 2.5
|
15
|
+
end
|
16
|
+
p 3
|
17
|
+
snooze
|
18
|
+
p 4
|
19
|
+
# f.stop
|
20
|
+
# f.join
|
21
|
+
# Fiber.current.terminate_all_children
|
22
|
+
# Fiber.current.await_all_children
|
23
|
+
p 5
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "Child pid: #{pid}"
|
27
|
+
Process.wait(pid)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
pong = spin_loop do
|
7
|
+
msg, ping = receive
|
8
|
+
puts msg
|
9
|
+
ping << 'pong'
|
10
|
+
end
|
11
|
+
|
12
|
+
ping = spin_loop do
|
13
|
+
pong << ['ping', Fiber.current]
|
14
|
+
msg = receive
|
15
|
+
puts msg
|
16
|
+
end
|
17
|
+
|
18
|
+
suspend
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
f1 = spin do
|
7
|
+
f2 = spin { sleep 60 }
|
8
|
+
f3 = spin { sleep 60 }
|
9
|
+
sleep 60
|
10
|
+
ensure
|
11
|
+
p 1
|
12
|
+
f2.stop
|
13
|
+
p 2
|
14
|
+
f3.stop
|
15
|
+
p "should reach here!"
|
16
|
+
end
|
17
|
+
|
18
|
+
sleep 0.1
|
19
|
+
f1.stop
|
20
|
+
snooze
|
data/ext/gyro/async.c
CHANGED
data/ext/gyro/extconf.rb
CHANGED
@@ -16,8 +16,5 @@ $defs << "-DHAVE_SYS_RESOURCE_H" if have_header("sys/resource.h")
|
|
16
16
|
|
17
17
|
CONFIG["optflags"] << " -fno-strict-aliasing" unless RUBY_PLATFORM =~ /mswin/
|
18
18
|
|
19
|
-
CONFIG["optflags"] << " -Wcomment"
|
20
|
-
CONFIG["optflags"] << " -Wbitwise-op-parentheses"
|
21
|
-
|
22
19
|
dir_config "gyro_ext"
|
23
20
|
create_makefile "gyro_ext"
|