polyphony 0.99 → 0.99.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/.github/FUNDING.yml +1 -1
- data/.rubocop.yml +3 -3
- data/.yardopts +30 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE +1 -1
- data/README.md +63 -29
- data/Rakefile +1 -5
- data/TODO.md +0 -4
- data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
- data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
- data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
- data/docs/{main-concepts/extending.md → extending.md} +2 -9
- data/docs/faq.md +3 -16
- data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
- data/docs/link_rewriter.rb +16 -0
- data/docs/{getting-started/overview.md → overview.md} +1 -30
- data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
- data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
- data/examples/adapters/redis_client.rb +3 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_plain_ruby.rb +26 -0
- data/ext/polyphony/backend_io_uring.c +154 -9
- data/ext/polyphony/backend_io_uring_context.c +21 -12
- data/ext/polyphony/backend_io_uring_context.h +12 -7
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/extconf.rb +24 -8
- data/ext/polyphony/fiber.c +79 -2
- data/ext/polyphony/io_extensions.c +53 -0
- data/ext/polyphony/pipe.c +42 -2
- data/ext/polyphony/polyphony.c +345 -31
- data/ext/polyphony/polyphony.h +9 -2
- data/ext/polyphony/queue.c +181 -0
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +8 -1
- data/ext/polyphony/runqueue_ring_buffer.c +13 -0
- data/ext/polyphony/runqueue_ring_buffer.h +2 -1
- data/ext/polyphony/socket_extensions.c +6 -0
- data/ext/polyphony/thread.c +34 -2
- data/lib/polyphony/adapters/process.rb +11 -1
- data/lib/polyphony/adapters/sequel.rb +1 -1
- data/lib/polyphony/core/channel.rb +2 -0
- data/lib/polyphony/core/debug.rb +1 -1
- data/lib/polyphony/core/global_api.rb +25 -24
- data/lib/polyphony/core/resource_pool.rb +7 -6
- data/lib/polyphony/core/sync.rb +2 -2
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/core/timer.rb +8 -8
- data/lib/polyphony/extensions/exception.rb +2 -0
- data/lib/polyphony/extensions/fiber.rb +15 -13
- data/lib/polyphony/extensions/io.rb +127 -5
- data/lib/polyphony/extensions/kernel.rb +20 -2
- data/lib/polyphony/extensions/openssl.rb +100 -11
- data/lib/polyphony/extensions/pipe.rb +103 -7
- data/lib/polyphony/extensions/process.rb +13 -1
- data/lib/polyphony/extensions/socket.rb +93 -27
- data/lib/polyphony/extensions/thread.rb +9 -1
- data/lib/polyphony/extensions/timeout.rb +1 -1
- data/lib/polyphony/version.rb +2 -1
- data/lib/polyphony.rb +27 -7
- data/polyphony.gemspec +1 -8
- data/test/stress.rb +1 -1
- data/test/test_global_api.rb +45 -7
- data/test/test_socket.rb +96 -0
- data/test/test_timer.rb +5 -5
- metadata +17 -40
- data/docs/_config.yml +0 -64
- data/docs/_includes/head.html +0 -40
- data/docs/_includes/title.html +0 -1
- data/docs/_sass/custom/custom.scss +0 -10
- data/docs/_sass/overrides.scss +0 -0
- data/docs/api-reference/exception.md +0 -31
- data/docs/api-reference/fiber.md +0 -425
- data/docs/api-reference/index.md +0 -9
- data/docs/api-reference/io.md +0 -36
- data/docs/api-reference/object.md +0 -99
- data/docs/api-reference/polyphony-baseexception.md +0 -33
- data/docs/api-reference/polyphony-cancel.md +0 -26
- data/docs/api-reference/polyphony-moveon.md +0 -24
- data/docs/api-reference/polyphony-net.md +0 -20
- data/docs/api-reference/polyphony-process.md +0 -28
- data/docs/api-reference/polyphony-resourcepool.md +0 -59
- data/docs/api-reference/polyphony-restart.md +0 -18
- data/docs/api-reference/polyphony-terminate.md +0 -18
- data/docs/api-reference/polyphony-threadpool.md +0 -67
- data/docs/api-reference/polyphony-throttler.md +0 -77
- data/docs/api-reference/polyphony.md +0 -36
- data/docs/api-reference/thread.md +0 -88
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +0 -10
- data/docs/getting-started/installing.md +0 -34
- /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
- /data/{docs → assets}/polyphony-logo.png +0 -0
- /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
data/docs/api-reference/fiber.md
DELETED
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: ::Fiber
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/fiber/
|
|
6
|
-
# prev_title: Tutorial
|
|
7
|
-
# next_title: How Fibers are Scheduled
|
|
8
|
-
---
|
|
9
|
-
# ::Fiber
|
|
10
|
-
|
|
11
|
-
[Ruby core Fiber documentation](https://ruby-doc.org/core-2.7.0/Fiber.html)
|
|
12
|
-
|
|
13
|
-
Polyphony enhances the core `Fiber` class with APIs for scheduling, exception
|
|
14
|
-
handling, message passing, and more. Normally, fibers should be created using
|
|
15
|
-
`Object#spin` or `Fiber#spin`, but some fibers might be created implicitly when
|
|
16
|
-
using lazy enumerators or third party gems. For fibers created implicitly,
|
|
17
|
-
Polyphony provides `Fiber#setup_raw`, which enables scheduling and message
|
|
18
|
-
passing for such fibers.
|
|
19
|
-
|
|
20
|
-
While most work on fibers since their introduction into MRI Ruby has
|
|
21
|
-
concentrated on `Fiber#resume` and `Fiber.yield` for transferring control
|
|
22
|
-
between fibers, Polyphony uses `Fiber#transfer` exclusively, which allows
|
|
23
|
-
fully symmetric transfer of control between fibers.
|
|
24
|
-
|
|
25
|
-
## Class Methods
|
|
26
|
-
|
|
27
|
-
### ::await(\*fibers) → [\*result]
|
|
28
|
-
|
|
29
|
-
Awaits all given fibers, returning when all fibers have terminated. If one of
|
|
30
|
-
the given fibers terminates with an uncaught exception, `::await` will terminate
|
|
31
|
-
and await all fibers that are still running, then reraise the exception. All the
|
|
32
|
-
given fibers are guaranteed to have terminated when `::await` returns. If no
|
|
33
|
-
exception is raised, `::await` returns an array containing the results of all
|
|
34
|
-
given fibers, in the same order.
|
|
35
|
-
|
|
36
|
-
```ruby
|
|
37
|
-
f1 = spin { sleep 1 }
|
|
38
|
-
f2 = spin { sleep 2 }
|
|
39
|
-
Fiber.await(f1, f2)
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### ::select(\*fibers) → [\*result]
|
|
43
|
-
|
|
44
|
-
Selects the first fiber to have terminated among the given fibers. If any of the
|
|
45
|
-
given fibers terminates with an uncaught exception, `::select` will reraise the
|
|
46
|
-
exception. If no exception is raised, `::select` returns an array containing the
|
|
47
|
-
fiber and its result. All given fibers are guaranteed to have terminated when
|
|
48
|
-
`::select` returns.
|
|
49
|
-
|
|
50
|
-
```ruby
|
|
51
|
-
# get the fastest reply of a bunch of URLs
|
|
52
|
-
fibers = urls.map { |u| spin { [u, HTTParty.get(u)] } }
|
|
53
|
-
fiber, (url, result) = Fiber.select(*fibers)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Instance methods
|
|
57
|
-
|
|
58
|
-
### #<<(object) → fiber<br>#send(object) → fiber
|
|
59
|
-
|
|
60
|
-
Adds a message to the fiber's mailbox. The message can be any object. This
|
|
61
|
-
method is complemented by `Fiber#receive`.
|
|
62
|
-
|
|
63
|
-
```ruby
|
|
64
|
-
f = spin do
|
|
65
|
-
loop do
|
|
66
|
-
receiver, x = receive
|
|
67
|
-
receiver << x * 10
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
f << 2
|
|
71
|
-
result = receive #=> 20
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### #auto_watcher → async
|
|
75
|
-
|
|
76
|
-
Returns a reusable `Gyro::Async` watcher instance associated with the fiber.
|
|
77
|
-
This method provides a way to minimize watcher allocation. Instead of allocating
|
|
78
|
-
a new async watcher every time one is needed, the same watcher associated with
|
|
79
|
-
the fiber is reused.
|
|
80
|
-
|
|
81
|
-
```ruby
|
|
82
|
-
def work(async)
|
|
83
|
-
do_something
|
|
84
|
-
async.signal
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
async = Fiber.current.auto_watcher
|
|
88
|
-
spin { work(async) }
|
|
89
|
-
async.await
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### #await → object<br>#join → object
|
|
93
|
-
|
|
94
|
-
Awaits the termination of the fiber. If the fiber terminates with an uncaught
|
|
95
|
-
exception, `#await` will reraise the exception. Otherwise `#await` returns the
|
|
96
|
-
result of the fiber.
|
|
97
|
-
|
|
98
|
-
```ruby
|
|
99
|
-
f = spin { 'foo' }
|
|
100
|
-
f.await #=> 'foo'
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### #await_all_children → fiber
|
|
104
|
-
|
|
105
|
-
Waits for all the fiber's child fibers to terminate. This method is normally
|
|
106
|
-
coupled with `Fiber#terminate_all_children`. See also
|
|
107
|
-
`Fiber#shutdown_all_children`.
|
|
108
|
-
|
|
109
|
-
```ruby
|
|
110
|
-
jobs.each { |j| spin { process(j) } }
|
|
111
|
-
sleep 1
|
|
112
|
-
terminate_all_children
|
|
113
|
-
await_all_children
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### #caller → [*location]
|
|
117
|
-
|
|
118
|
-
Return the execution stack of the fiber, including that of the fiber from which
|
|
119
|
-
it was spun.
|
|
120
|
-
|
|
121
|
-
```ruby
|
|
122
|
-
spin {
|
|
123
|
-
spin {
|
|
124
|
-
spin {
|
|
125
|
-
pp Fiber.current.caller
|
|
126
|
-
}.await
|
|
127
|
-
}.await
|
|
128
|
-
}.await
|
|
129
|
-
|
|
130
|
-
#=> ["examples/core/xx-caller.rb:3:in `block (2 levels) in <main>'",
|
|
131
|
-
#=> "examples/core/xx-caller.rb:2:in `block in <main>'",
|
|
132
|
-
#=> "examples/core/xx-caller.rb:1:in `<main>'"]
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### #cancel! → fiber
|
|
136
|
-
|
|
137
|
-
Terminates the fiber by raising a `Polyphony::Cancel` exception. If uncaught,
|
|
138
|
-
the exception will be propagated.
|
|
139
|
-
|
|
140
|
-
```ruby
|
|
141
|
-
f = spin { sleep 1 }
|
|
142
|
-
f.cancel! #=> exception: Polyphony::Cancel
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### #children → [\*fiber]
|
|
146
|
-
|
|
147
|
-
Returns an array containing all of the fiber's child fibers. A child fiber's
|
|
148
|
-
lifetime is limited to that of its immediate parent.
|
|
149
|
-
|
|
150
|
-
```ruby
|
|
151
|
-
f1 = spin { sleep 1 }
|
|
152
|
-
f2 = spin { sleep 1 }
|
|
153
|
-
f3 = spin { sleep 1 }
|
|
154
|
-
Fiber.current.children #=> [f1, f2, f3]
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### #interrupt(object = nil) → fiber<br>#stop(object = nil) → fiber
|
|
158
|
-
|
|
159
|
-
Terminates the fiber by raising a `Polyphony::MoveOn` exception in its context.
|
|
160
|
-
The given object will be set as the fiber's result. Note that a `MoveOn`
|
|
161
|
-
exception is never propagated.
|
|
162
|
-
|
|
163
|
-
```ruby
|
|
164
|
-
f = spin { do_something_slow }
|
|
165
|
-
f.interrupt('never mind')
|
|
166
|
-
f.await #=> 'never mind'
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### #location → string
|
|
170
|
-
|
|
171
|
-
Returns the location of the fiber's associated block, or `(root)` for the main
|
|
172
|
-
fiber.
|
|
173
|
-
|
|
174
|
-
### #main? → true or false
|
|
175
|
-
|
|
176
|
-
Returns true if the fiber is the main fiber for its thread.
|
|
177
|
-
|
|
178
|
-
### #parent → fiber
|
|
179
|
-
|
|
180
|
-
Returns the fiber's parent fiber. The main fiber's parent is nil.
|
|
181
|
-
|
|
182
|
-
```ruby
|
|
183
|
-
f = spin { sleep 1 }
|
|
184
|
-
f.parent #=> Fiber.current
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### #raise(\*args) → fiber
|
|
188
|
-
|
|
189
|
-
Raises an error in the context of the fiber. The given exception can be a string
|
|
190
|
-
(for raising `RuntimeError` exceptions with a given message), an exception
|
|
191
|
-
class, or an exception instance. If no argument is given, a `RuntimeError` will
|
|
192
|
-
be raised. Uncaught exceptions will be propagated.
|
|
193
|
-
|
|
194
|
-
```ruby
|
|
195
|
-
f = spin { sleep 1 }
|
|
196
|
-
f.raise('foo') # raises a RuntimeError
|
|
197
|
-
f.raise(MyException, 'my error message') # exception class with message
|
|
198
|
-
f.raise(MyException.new('my error message')) # exception instance
|
|
199
|
-
# or simply
|
|
200
|
-
f.raise
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### #receive → object
|
|
204
|
-
|
|
205
|
-
Pops the first message from the fiber's mailbox. If no message is available,
|
|
206
|
-
`#receive` will block until a message is pushed to the mailbox. The received
|
|
207
|
-
message can be any kind of object. This method is complemented by
|
|
208
|
-
`Fiber#<<`/`Fiber#send`.
|
|
209
|
-
|
|
210
|
-
```ruby
|
|
211
|
-
spin { Fiber.current.parent << 'hello from child' }
|
|
212
|
-
message = receive #=> 'hello from child'
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### #receive_all_pending → [*object]
|
|
216
|
-
|
|
217
|
-
Returns all messages currently in the mailbox, emptying the mailbox. This method
|
|
218
|
-
does not block if no the mailbox is already empty. This method may be used to
|
|
219
|
-
process any pending messages upon fiber termination:
|
|
220
|
-
|
|
221
|
-
```ruby
|
|
222
|
-
worker = spin do
|
|
223
|
-
loop do
|
|
224
|
-
job = receive
|
|
225
|
-
handle_job(job)
|
|
226
|
-
end
|
|
227
|
-
rescue Polyphony::Terminate => e
|
|
228
|
-
receive_all_pending.each { |job| handle_job(job) }
|
|
229
|
-
end
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### #restart(object = nil) → fiber<br>#reset(object = nil) → fiber
|
|
233
|
-
|
|
234
|
-
Restarts the fiber, essentially rerunning the fiber's associated block,
|
|
235
|
-
restoring it to its primary state. If the fiber is already terminated, a new
|
|
236
|
-
fiber will be created and returned. If the fiber's block takes an argument, its
|
|
237
|
-
value can be set by passing it to `#restart`.
|
|
238
|
-
|
|
239
|
-
```ruby
|
|
240
|
-
counter = 0
|
|
241
|
-
f = spin { sleep 1; counter += 1 }
|
|
242
|
-
f.await #=> 1
|
|
243
|
-
f.restart
|
|
244
|
-
f.await #=> 2
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### #result → object
|
|
248
|
-
|
|
249
|
-
Returns the result of the fiber. If the fiber has not yet terminated, `nil` is
|
|
250
|
-
returned. If the fiber terminated with an uncaught exception, the exception is
|
|
251
|
-
returned.
|
|
252
|
-
|
|
253
|
-
```ruby
|
|
254
|
-
f = spin { sleep 1; 'foo' }
|
|
255
|
-
f.await
|
|
256
|
-
f.result #=> 'foo'
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### #running? → true or false
|
|
260
|
-
|
|
261
|
-
Returns true if the fiber is not yet terminated.
|
|
262
|
-
|
|
263
|
-
### #schedule(object = nil) → fiber
|
|
264
|
-
|
|
265
|
-
Adds the fiber to its thread's run queue. The fiber will be eventually resumed
|
|
266
|
-
with the given value, which can be any object. If an exception is given, it will
|
|
267
|
-
be raised in the context of the fiber upon resuming. If the fiber is already on
|
|
268
|
-
the run queue, the resume value will be updated.
|
|
269
|
-
|
|
270
|
-
```ruby
|
|
271
|
-
f = spin do
|
|
272
|
-
result = suspend
|
|
273
|
-
p result
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
sleep 0.1
|
|
277
|
-
f.schedule 'foo'
|
|
278
|
-
f.await
|
|
279
|
-
#=> 'foo'
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### #shutdown_all_children → fiber
|
|
283
|
-
|
|
284
|
-
Terminates all of the fiber's child fibers and blocks until all are terminated.
|
|
285
|
-
This method is can be used to replace calls to `#terminate_all_children`
|
|
286
|
-
followed by `#await_all_children`.
|
|
287
|
-
|
|
288
|
-
```ruby
|
|
289
|
-
jobs.each { |j| spin { process(j) } }
|
|
290
|
-
sleep 1
|
|
291
|
-
shutdown_all_children
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### #spin(tag = nil, { block }) → fiber
|
|
295
|
-
|
|
296
|
-
Creates a new fiber with self as its parent. The returned fiber is put on the
|
|
297
|
-
run queue of the parent fiber's associated thread. A tag of any object type can
|
|
298
|
-
be associated with the fiber. Note that `Object#spin` is a shortcut for
|
|
299
|
-
`Fiber.current.spin`.
|
|
300
|
-
|
|
301
|
-
```ruby
|
|
302
|
-
f = Fiber.current.spin { |x|'foo' }
|
|
303
|
-
f.await #=> 'foo'
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
If the block takes an argument, its value can be controlled by explicitly
|
|
307
|
-
calling `Fiber#schedule`. The result of the given block (the value of the last
|
|
308
|
-
statement in the block) can be retrieved using `Fiber#result` or by otherwise
|
|
309
|
-
using fiber control APIs such as `Fiber#await`.
|
|
310
|
-
|
|
311
|
-
```ruby
|
|
312
|
-
f = spin { |x| x * 10 }
|
|
313
|
-
f.schedule(2)
|
|
314
|
-
f.await #=> 20
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### #state → symbol
|
|
318
|
-
|
|
319
|
-
Returns the fiber's current state, which can be any of the following:
|
|
320
|
-
|
|
321
|
-
- `:waiting` - the fiber is currently waiting for an operation to complete.
|
|
322
|
-
- `:runnable` - the fiber is scheduled to be resumed (put on the run queue).
|
|
323
|
-
- `:running` - the fiber is currently running.
|
|
324
|
-
- `:dead` - the fiber has terminated.
|
|
325
|
-
|
|
326
|
-
### #supervise(opts = {}) → fiber
|
|
327
|
-
|
|
328
|
-
Supervises all child fibers, optionally restarting any fiber that terminates.
|
|
329
|
-
|
|
330
|
-
The given `opts` argument controls the behaviour of the supervision. The
|
|
331
|
-
following options are currently supported:
|
|
332
|
-
|
|
333
|
-
- `:restart`: restart options
|
|
334
|
-
- `nil` - Child fibers are not restarted (default behaviour).
|
|
335
|
-
- `true` - Any child fiber that terminates is restarted.
|
|
336
|
-
- `:on_error` - Any child fiber that terminates with an uncaught exception is
|
|
337
|
-
restarted.
|
|
338
|
-
- `:watcher`: a fiber watching supervision events.
|
|
339
|
-
|
|
340
|
-
If a watcher fiber is specified, it will receive supervision events to its
|
|
341
|
-
mailbox. The events are of the form `[<event_type>, <fiber>]`, for example
|
|
342
|
-
`[:restart, child_fiber_1]`. Here's an example of using a watcher fiber:
|
|
343
|
-
|
|
344
|
-
```ruby
|
|
345
|
-
watcher = spin_loop do
|
|
346
|
-
kind, fiber = receive
|
|
347
|
-
case kind
|
|
348
|
-
when :restart
|
|
349
|
-
puts "fiber #{fiber.inspect} restarted"
|
|
350
|
-
end
|
|
351
|
-
end
|
|
352
|
-
...
|
|
353
|
-
supervise(restart: true, watcher: watcher)
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### #tag → object
|
|
357
|
-
|
|
358
|
-
Returns the tag associated with the fiber, normally passed to `Fiber#spin`. The
|
|
359
|
-
tag can be any kind of object. The default tag is `nil`.
|
|
360
|
-
|
|
361
|
-
```ruby
|
|
362
|
-
f = spin(:worker) { do_some_work }
|
|
363
|
-
f.tag #=> :worker
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### #tag=(object) → object
|
|
367
|
-
|
|
368
|
-
Sets the tag associated with the fiber. The tag can be any kind of object.
|
|
369
|
-
|
|
370
|
-
```ruby
|
|
371
|
-
f = spin { do_some_work }
|
|
372
|
-
f.tag = :worker
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
### #terminate → fiber
|
|
376
|
-
|
|
377
|
-
Terminates the fiber by raising a `Polyphony::Terminate` exception. The
|
|
378
|
-
exception is not propagated. Note that the fiber is not guaranteed to terminate
|
|
379
|
-
before `#terminate` returns. The fiber will need to run first in order to raise
|
|
380
|
-
the `Terminate` exception and terminate. This method is normally coupled with
|
|
381
|
-
`Fiber#await`:
|
|
382
|
-
|
|
383
|
-
```ruby
|
|
384
|
-
f1 = spin { sleep 1 }
|
|
385
|
-
f2 = spin { sleep 2 }
|
|
386
|
-
|
|
387
|
-
f1.await
|
|
388
|
-
|
|
389
|
-
f2.terminate
|
|
390
|
-
f2.await
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
### #terminate_all_children → fiber
|
|
394
|
-
|
|
395
|
-
Terminates all of the fiber's child fibers. Note that `#terminate_all_children`
|
|
396
|
-
does not acutally wait for all child fibers to terminate. This method is
|
|
397
|
-
normally coupled with `Fiber#await_all_children`. See also `Fiber#shutdown_all_children`.
|
|
398
|
-
|
|
399
|
-
```ruby
|
|
400
|
-
jobs.each { |j| spin { process(j) } }
|
|
401
|
-
sleep 1
|
|
402
|
-
terminate_all_children
|
|
403
|
-
await_all_children
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
### #thread → thread
|
|
407
|
-
|
|
408
|
-
Returns the thread to which the fiber belongs.
|
|
409
|
-
|
|
410
|
-
```ruby
|
|
411
|
-
f = spin(:worker) { do_some_work }
|
|
412
|
-
f.thread #=> Thread.current
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
### #when_done({ block }) → fiber
|
|
416
|
-
|
|
417
|
-
Installs a hook to be called when the fiber is terminated. The block will be
|
|
418
|
-
called with the fiber's result. If the fiber terminates with an uncaught
|
|
419
|
-
exception, the exception will be passed to the block.
|
|
420
|
-
|
|
421
|
-
```ruby
|
|
422
|
-
f = spin { 'foo' }
|
|
423
|
-
f.when_done { |r| puts "got #{r} from fiber" }
|
|
424
|
-
f.await #=> STDOUT: 'got foo from fiber'
|
|
425
|
-
```
|
data/docs/api-reference/index.md
DELETED
data/docs/api-reference/io.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: ::IO
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/io/
|
|
6
|
-
---
|
|
7
|
-
# ::IO
|
|
8
|
-
|
|
9
|
-
[Ruby core IO documentation](https://ruby-doc.org/core-2.7.0/IO.html)
|
|
10
|
-
|
|
11
|
-
Polyphony reimplements a significant number of IO class and instance methods to
|
|
12
|
-
be fiber-aware. Polyphony also adds methods for accessing the associated event
|
|
13
|
-
watchers.
|
|
14
|
-
|
|
15
|
-
## Class Methods
|
|
16
|
-
|
|
17
|
-
## Instance methods
|
|
18
|
-
|
|
19
|
-
### #read_watcher → io_watcher
|
|
20
|
-
|
|
21
|
-
Returns the read watcher associated with the IO. The watcher is automatically
|
|
22
|
-
created and cached. The watcher is an instance of `Gyro::IO`. Normally this
|
|
23
|
-
method is not called directly from application code.
|
|
24
|
-
|
|
25
|
-
```ruby
|
|
26
|
-
def read_ten_chars(io)
|
|
27
|
-
io.read_watcher.await
|
|
28
|
-
io.read(10)
|
|
29
|
-
end
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### #write_watcher → io_watcher
|
|
33
|
-
|
|
34
|
-
Returns the write watcher associated with the IO. The watcher is automatically
|
|
35
|
-
created and cached. The watcher is an instance of `Gyro::IO`. Normally this
|
|
36
|
-
method is not called directly from application code.
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: ::Object (Global API)
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/object/
|
|
6
|
-
---
|
|
7
|
-
# ::Object (Global API)
|
|
8
|
-
|
|
9
|
-
The global Polyphony API is designed to feel almost like a part of the Ruby
|
|
10
|
-
runtime. The global API contains multiple methods for creating and controlling
|
|
11
|
-
fibers, as well as miscellaneous methods for dealing with timers and other
|
|
12
|
-
events, with minimal boilerplate. The API is implemented as a module included in
|
|
13
|
-
the `Object` class, allowing access from any receiver.
|
|
14
|
-
|
|
15
|
-
### #after(interval, { block }) → fiber
|
|
16
|
-
|
|
17
|
-
Run the given block after the given time interval (specified in seconds). This
|
|
18
|
-
method spins up a separate fiber that will sleep for the given interval, then
|
|
19
|
-
run the given block.
|
|
20
|
-
|
|
21
|
-
```ruby
|
|
22
|
-
f = spin { do_some_big_work }
|
|
23
|
-
after(1) { f.stop }
|
|
24
|
-
f.await
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### #cancel_after(interval, { block }) → object
|
|
28
|
-
|
|
29
|
-
Run the given block, cancelling it after the given time interval by raising a
|
|
30
|
-
`Polyphony::Cancel` exception. If uncaught, the exception will be propagated.
|
|
31
|
-
|
|
32
|
-
```ruby
|
|
33
|
-
spin do
|
|
34
|
-
cancel_after(3) { do_some_work }
|
|
35
|
-
rescue Polyphony::Cancel
|
|
36
|
-
puts "work was cancelled"
|
|
37
|
-
end
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### #every(interval, { block }) → object
|
|
41
|
-
|
|
42
|
-
Runs the given block repeatedly, at the given time interval. This method will
|
|
43
|
-
block until an exception is raised.
|
|
44
|
-
|
|
45
|
-
```ruby
|
|
46
|
-
every(3) do
|
|
47
|
-
puts "I'm still alive"
|
|
48
|
-
end
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### #move_on_after(interval, with_value: nil, { block }) → object
|
|
52
|
-
|
|
53
|
-
Run the given block, interrupting it after the given time interval by raising a
|
|
54
|
-
`Polyphony::MoveOn` exception. The `with_value` keyword argument can be used to
|
|
55
|
-
set the value returned from the block if the timeout has elapsed.
|
|
56
|
-
|
|
57
|
-
```ruby
|
|
58
|
-
result = move_on_after(3, with_value: 'bar') { sleep 5; 'foo' }
|
|
59
|
-
result #=> 'bar'
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### #receive → object
|
|
63
|
-
|
|
64
|
-
Shortcut for `Fiber.current.receive`
|
|
65
|
-
|
|
66
|
-
### #receive_all_pending → [*object]
|
|
67
|
-
|
|
68
|
-
Shortcut for `Fiber.current.receive_all_pending`
|
|
69
|
-
|
|
70
|
-
### #sleep(duration = nil) → fiber
|
|
71
|
-
|
|
72
|
-
Sleeps for the given duration.
|
|
73
|
-
|
|
74
|
-
### #spin(tag = nil, { block}) → fiber
|
|
75
|
-
|
|
76
|
-
Shortcut for `Fiber.current.spin`
|
|
77
|
-
|
|
78
|
-
### #spin_loop(tag = nil, rate: nil, &block) → fiber
|
|
79
|
-
|
|
80
|
-
Spins up a new fiber that runs the given block in a loop. If `rate` is given,
|
|
81
|
-
the loop is throttled to run `rate` times per second.
|
|
82
|
-
|
|
83
|
-
```ruby
|
|
84
|
-
# print twice a second
|
|
85
|
-
f = spin_loop(rate: 2) { puts 'hello world' }
|
|
86
|
-
sleep 2
|
|
87
|
-
f.stop
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### #throttled_loop(rate, count: nil, &block) → object
|
|
91
|
-
|
|
92
|
-
Runs the given block in a loop at the given rate (times per second). If `count`
|
|
93
|
-
is given, the loop will be run for the specified number of times and then
|
|
94
|
-
returns. Otherwise, the loop is infinite (unless an exception is raised).
|
|
95
|
-
|
|
96
|
-
```ruby
|
|
97
|
-
# twice a second
|
|
98
|
-
throttled_loop(2) { puts 'hello world' }
|
|
99
|
-
```
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: Polyphony::BaseException
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/polyphony-baseexception/
|
|
6
|
-
---
|
|
7
|
-
# Polyphony::BaseException
|
|
8
|
-
|
|
9
|
-
The `Polyphony::BaseException` is a common base class for exceptions used to
|
|
10
|
-
control fiber execution. Instances of descendant classes are meant to be created
|
|
11
|
-
explicitly using `new`, e.g. `Polyphony::MoveOn.new`, rather than using `raise
|
|
12
|
-
Polyphony::MoveOn`. Normally an application will not use those classes directly
|
|
13
|
-
but would rather use APIs such as `Fiber#interrupt`.
|
|
14
|
-
|
|
15
|
-
## Derived classes
|
|
16
|
-
|
|
17
|
-
- [`Polyphony::Cancel`](../polyphony-cancel/)
|
|
18
|
-
- [`Polyphony::MoveOn`](../polyphony-moveon/)
|
|
19
|
-
- [`Polyphony::Restart`](../polyphony-restart/)
|
|
20
|
-
- [`Polyphony::Terminate`](../polyphony-terminate/)
|
|
21
|
-
|
|
22
|
-
## Instance methods
|
|
23
|
-
|
|
24
|
-
### #initialize(value = nil)
|
|
25
|
-
|
|
26
|
-
Initializes the exception with an optional result value. The value will be used
|
|
27
|
-
as the result of the block being interrupted or the fiber being terminated.
|
|
28
|
-
|
|
29
|
-
```ruby
|
|
30
|
-
f = spin { 'foo' }
|
|
31
|
-
f.raise(Polyphony::Terminate.new('bar'))
|
|
32
|
-
f.await #=> 'bar'
|
|
33
|
-
```
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: Polyphony::Cancel
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/polyphony-cancel/
|
|
6
|
-
---
|
|
7
|
-
# Polyphony::Cancel
|
|
8
|
-
|
|
9
|
-
`Polyphony::Cancel` is an exception class used to interrupt a blocking operation
|
|
10
|
-
with an exception that must be rescued. This exception is will propagate if not
|
|
11
|
-
rescued. A `Polyphony::Cancel` exception is normally raised using APIs such as
|
|
12
|
-
`Fiber#cancel!` or `Object#cancel_after`.
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
require 'httparty'
|
|
16
|
-
require 'time'
|
|
17
|
-
|
|
18
|
-
def current_server_time
|
|
19
|
-
cancel_after(10) do
|
|
20
|
-
response_body = HTTParty.get(TIME_URL).body
|
|
21
|
-
Time.parse(response_body)
|
|
22
|
-
end
|
|
23
|
-
rescue Polyphony::Cancel
|
|
24
|
-
Time.now
|
|
25
|
-
end
|
|
26
|
-
```
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: Polyphony::MoveOn
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/polyphony-moveon/
|
|
6
|
-
---
|
|
7
|
-
# Polyphony::MoveOn
|
|
8
|
-
|
|
9
|
-
`Polyphony::MoveOn` is an exception class used to interrupt a blocking operation
|
|
10
|
-
without propagating the excception. A `Polyphony::MoveOn` exception is normally
|
|
11
|
-
raised using APIs such as `Fiber#interrupt` or `Object#move_on_after`. This
|
|
12
|
-
exception allows you to set the result of the operation being interrupted.
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
|
|
16
|
-
def do_something_slow
|
|
17
|
-
sleep 10
|
|
18
|
-
'foo'
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
f = spin { do_something_slow }
|
|
22
|
-
f.interrupt('bar')
|
|
23
|
-
f.await #=> 'bar'
|
|
24
|
-
```
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: Polyphony::Net
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/polyphony-net/
|
|
6
|
-
---
|
|
7
|
-
# Polyphony::Net
|
|
8
|
-
|
|
9
|
-
The `Polyphony::Net` provides convenience methods for working with sockets. The
|
|
10
|
-
module unifies secure and non-secure socket APIs.
|
|
11
|
-
|
|
12
|
-
## Class Methods
|
|
13
|
-
|
|
14
|
-
### #tcp_connect(host, port, opts = {}) → socket
|
|
15
|
-
|
|
16
|
-
Connects to a TCP server.
|
|
17
|
-
|
|
18
|
-
### #tcp_listen(host = nil, port = nil, opts = {}) → socket
|
|
19
|
-
|
|
20
|
-
Opens a server socket for listening to incoming connections.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: page
|
|
3
|
-
title: Polyphony::Process
|
|
4
|
-
parent: API Reference
|
|
5
|
-
permalink: /api-reference/polyphony-process/
|
|
6
|
-
---
|
|
7
|
-
# Polyphony::Process
|
|
8
|
-
|
|
9
|
-
The `Polyphony::Process` module is used to watch child processes.
|
|
10
|
-
|
|
11
|
-
## Class Methods
|
|
12
|
-
|
|
13
|
-
### #watch(cmd = nil, { block })
|
|
14
|
-
|
|
15
|
-
Starts a child process, blocking until the child process terminates. If `#watch`
|
|
16
|
-
is interrupted before the child process terminates, the child process is sent a
|
|
17
|
-
`TERM` signal, and awaited. After 5 seconds, if the child has still not
|
|
18
|
-
terminated, it will be sent a `KILL` signal and awaited. This method is normally
|
|
19
|
-
used in conjunction with `#supervise` in order to supervise child processes.
|
|
20
|
-
|
|
21
|
-
If `cmd` is given, the child process is started using `Kernel#spawn` running a
|
|
22
|
-
shell command. If a block is given, the child process is started using
|
|
23
|
-
[`Polyphony#fork`](../polyphony/#fork-block---pid).
|
|
24
|
-
|
|
25
|
-
```ruby
|
|
26
|
-
spin { Polyphony::Process.watch('echo "Hello World"; sleep 1') }
|
|
27
|
-
supervise(restart: :always)
|
|
28
|
-
```
|