polyphony 0.99.5 → 1.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/.rubocop.yml +1 -0
- data/.yardopts +0 -2
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/docs/readme.md +1 -1
- data/docs/tutorial.md +2 -2
- data/ext/polyphony/fiber.c +1 -1
- data/ext/polyphony/pipe.c +0 -2
- data/ext/polyphony/polyphony.c +9 -11
- data/ext/polyphony/queue.c +0 -2
- data/ext/polyphony/thread.c +1 -1
- data/lib/polyphony/adapters/process.rb +1 -3
- data/lib/polyphony/core/debug.rb +0 -3
- data/lib/polyphony/core/exceptions.rb +0 -4
- data/lib/polyphony/core/sync.rb +4 -6
- data/lib/polyphony/core/thread_pool.rb +1 -5
- data/lib/polyphony/core/timer.rb +0 -6
- data/lib/polyphony/extensions/fiber.rb +14 -11
- data/lib/polyphony/extensions/io.rb +2 -2
- data/lib/polyphony/extensions/object.rb +283 -2
- data/lib/polyphony/extensions/openssl.rb +3 -3
- data/lib/polyphony/extensions/pipe.rb +2 -2
- data/lib/polyphony/extensions/socket.rb +9 -9
- data/lib/polyphony/extensions/thread.rb +3 -5
- data/lib/polyphony/net.rb +0 -1
- data/lib/polyphony/version.rb +1 -1
- metadata +5 -9
- data/docs/index.md +0 -94
- data/docs/link_rewriter.rb +0 -17
- data/docs/main-concepts/index.md +0 -9
- data/lib/polyphony/core/global_api.rb +0 -295
- /data/{assets → docs/assets}/echo-fibers.svg +0 -0
- /data/{assets → docs/assets}/polyphony-logo.png +0 -0
- /data/{assets → docs/assets}/sleeping-fiber.svg +0 -0
@@ -1,295 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './throttler'
|
4
|
-
|
5
|
-
module Polyphony
|
6
|
-
|
7
|
-
# Global API methods to be included in `::Object`
|
8
|
-
module GlobalAPI
|
9
|
-
|
10
|
-
# Spins up a fiber that will run the given block after sleeping for the
|
11
|
-
# given delay.
|
12
|
-
#
|
13
|
-
# @param interval [Number] delay in seconds before running the given block
|
14
|
-
# @return [Fiber] spun fiber
|
15
|
-
def after(interval, &block)
|
16
|
-
spin do
|
17
|
-
sleep interval
|
18
|
-
block.()
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Runs the given block after setting up a cancellation timer for
|
23
|
-
# cancellation. If the cancellation timer elapses, the execution will be
|
24
|
-
# interrupted with an exception defaulting to `Polyphony::Cancel`.
|
25
|
-
#
|
26
|
-
# This method should be used when a timeout should cause an exception to be
|
27
|
-
# propagated down the call stack or up the fiber tree.
|
28
|
-
#
|
29
|
-
# Example of normal use:
|
30
|
-
#
|
31
|
-
# def read_from_io_with_timeout(io)
|
32
|
-
# cancel_after(10) { io.read }
|
33
|
-
# rescue Polyphony::Cancel
|
34
|
-
# nil
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# The timeout period can be reset by passing a block that takes a single
|
38
|
-
# argument. The block will be provided with the canceller fiber. To reset
|
39
|
-
# the timeout, use `Fiber#reset`, as shown in the following example:
|
40
|
-
#
|
41
|
-
# cancel_after(10) do |timeout|
|
42
|
-
# loop do
|
43
|
-
# msg = socket.gets
|
44
|
-
# timeout.reset
|
45
|
-
# handle_msg(msg)
|
46
|
-
# end
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# @overload cancel_after(interval)
|
50
|
-
# @param interval [Number] timout in seconds
|
51
|
-
# @yield [Fiber] timeout fiber
|
52
|
-
# @return [any] block's return value
|
53
|
-
# @overload cancel_after(interval, with_exception: exception)
|
54
|
-
# @param interval [Number] timout in seconds
|
55
|
-
# @param with_exception [Class, Exception] exception or exception class
|
56
|
-
# @yield [Fiber] timeout fiber
|
57
|
-
# @return [any] block's return value
|
58
|
-
# @overload cancel_after(interval, with_exception: [klass, message])
|
59
|
-
# @param interval [Number] timout in seconds
|
60
|
-
# @param with_exception [Array] array containing class and message to use as exception
|
61
|
-
# @yield [Fiber] timeout fiber
|
62
|
-
# @return [any] block's return value
|
63
|
-
def cancel_after(interval, with_exception: Polyphony::Cancel, &block)
|
64
|
-
if block.arity > 0
|
65
|
-
cancel_after_with_optional_reset(interval, with_exception, &block)
|
66
|
-
else
|
67
|
-
Polyphony.backend_timeout(interval, with_exception, &block)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# Spins up a new fiber.
|
72
|
-
#
|
73
|
-
# @param tag [any] optional tag for the new fiber
|
74
|
-
# @return [Fiber] new fiber
|
75
|
-
def spin(tag = nil, &block)
|
76
|
-
Fiber.current.spin(tag, caller, &block)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Spins up a new fiber, running the given block inside an infinite loop. If
|
80
|
-
# `rate:` or `interval:` parameters are given, the loop is throttled
|
81
|
-
# accordingly.
|
82
|
-
#
|
83
|
-
# @param tag [any] optional tag for the new fiber
|
84
|
-
# @param rate [Number, nil] loop rate (times per second)
|
85
|
-
# @param interval [Number, nil] interval between consecutive iterations in seconds
|
86
|
-
# @return [Fiber] new fiber
|
87
|
-
def spin_loop(tag = nil, rate: nil, interval: nil, &block)
|
88
|
-
if rate || interval
|
89
|
-
Fiber.current.spin(tag, caller) do
|
90
|
-
throttled_loop(rate: rate, interval: interval, &block)
|
91
|
-
end
|
92
|
-
else
|
93
|
-
spin_loop_without_throttling(tag, caller, block)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Runs the given code, then waits for any child fibers of the current fibers
|
98
|
-
# to terminate.
|
99
|
-
#
|
100
|
-
# @return [any] given block's return value
|
101
|
-
def spin_scope(&block)
|
102
|
-
raise unless block
|
103
|
-
|
104
|
-
spin do
|
105
|
-
result = yield
|
106
|
-
Fiber.current.await_all_children
|
107
|
-
result
|
108
|
-
end.await
|
109
|
-
end
|
110
|
-
|
111
|
-
# Runs the given block in an infinite loop with a regular interval between
|
112
|
-
# consecutive iterations.
|
113
|
-
#
|
114
|
-
# @param interval [Number] interval between consecutive iterations in seconds
|
115
|
-
# @return [void]
|
116
|
-
def every(interval, &block)
|
117
|
-
Polyphony.backend_timer_loop(interval, &block)
|
118
|
-
end
|
119
|
-
|
120
|
-
# Runs the given block after setting up a cancellation timer for
|
121
|
-
# cancellation. If the cancellation timer elapses, the execution will be
|
122
|
-
# interrupted with a `Polyphony::MoveOn` exception, which will be rescued,
|
123
|
-
# and with cause the operation to return the given value.
|
124
|
-
#
|
125
|
-
# This method should be used when a timeout is to be handled locally,
|
126
|
-
# without generating an exception that is to propagated down the call stack
|
127
|
-
# or up the fiber tree.
|
128
|
-
#
|
129
|
-
# Example of normal use:
|
130
|
-
#
|
131
|
-
# move_on_after(10) {
|
132
|
-
# sleep 60
|
133
|
-
# 42
|
134
|
-
# } #=> nil
|
135
|
-
#
|
136
|
-
# move_on_after(10, with_value: :oops) {
|
137
|
-
# sleep 60
|
138
|
-
# 42
|
139
|
-
# } #=> :oops
|
140
|
-
#
|
141
|
-
# The timeout period can be reset by passing a block that takes a single
|
142
|
-
# argument. The block will be provided with the canceller fiber. To reset
|
143
|
-
# the timeout, use `Fiber#reset`, as shown in the following example:
|
144
|
-
#
|
145
|
-
# move_on_after(10) do |timeout|
|
146
|
-
# loop do
|
147
|
-
# msg = socket.gets
|
148
|
-
# timeout.reset
|
149
|
-
# handle_msg(msg)
|
150
|
-
# end
|
151
|
-
# end
|
152
|
-
#
|
153
|
-
# @overload move_on_after(interval) { ... }
|
154
|
-
# @param interval [Number] timout in seconds
|
155
|
-
# @yield [Fiber] timeout fiber
|
156
|
-
# @return [any] block's return value
|
157
|
-
# @overload move_on_after(interval, with_value: value) { ... }
|
158
|
-
# @param interval [Number] timout in seconds
|
159
|
-
# @param with_value [any] return value in case of timeout
|
160
|
-
# @yield [Fiber] timeout fiber
|
161
|
-
# @return [any] block's return value
|
162
|
-
def move_on_after(interval, with_value: nil, &block)
|
163
|
-
if block.arity > 0
|
164
|
-
move_on_after_with_optional_reset(interval, with_value, &block)
|
165
|
-
else
|
166
|
-
Polyphony.backend_timeout(interval, nil, with_value, &block)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# Returns the first message from the current fiber's mailbox. If the mailbox
|
171
|
-
# is empty, blocks until a message is available.
|
172
|
-
#
|
173
|
-
# @return [any] received message
|
174
|
-
def receive
|
175
|
-
Fiber.current.receive
|
176
|
-
end
|
177
|
-
|
178
|
-
# Returns all messages currently pending on the current fiber's mailbox.
|
179
|
-
#
|
180
|
-
# @return [Array] array of received messages
|
181
|
-
def receive_all_pending
|
182
|
-
Fiber.current.receive_all_pending
|
183
|
-
end
|
184
|
-
|
185
|
-
# Supervises the current fiber's children. See `Fiber#supervise` for
|
186
|
-
# options.
|
187
|
-
#
|
188
|
-
# @param args [Array] positional parameters
|
189
|
-
# @param opts [Hash] named parameters
|
190
|
-
# @return [void]
|
191
|
-
def supervise(*args, **opts, &block)
|
192
|
-
Fiber.current.supervise(*args, **opts, &block)
|
193
|
-
end
|
194
|
-
|
195
|
-
# Sleeps for the given duration. If the duration is `nil`, sleeps
|
196
|
-
# indefinitely.
|
197
|
-
#
|
198
|
-
# @param duration [Number, nil] duration
|
199
|
-
# @return [void]
|
200
|
-
def sleep(duration = nil)
|
201
|
-
duration ?
|
202
|
-
Polyphony.backend_sleep(duration) : Polyphony.backend_wait_event(true)
|
203
|
-
end
|
204
|
-
|
205
|
-
# Starts a throttled loop with the given rate. If `count:` is given, the
|
206
|
-
# loop is run for the given number of times. Otherwise, the loop is
|
207
|
-
# infinite. The loop rate (times per second) can be given as the rate
|
208
|
-
# parameter. The throttling can also be controlled by providing an
|
209
|
-
# `interval:` or `rate:` named parameter.
|
210
|
-
#
|
211
|
-
# @param rate [Number, nil] loop rate (times per second)
|
212
|
-
# @option opts [Number] :rate loop rate (times per second)
|
213
|
-
# @option opts [Number] :interval loop interval in seconds
|
214
|
-
# @option opts [Number] :count number of iterations (nil for infinite)
|
215
|
-
# @return [void]
|
216
|
-
def throttled_loop(rate = nil, **opts, &block)
|
217
|
-
throttler = Polyphony::Throttler.new(rate || opts)
|
218
|
-
if opts[:count]
|
219
|
-
opts[:count].times { |_i| throttler.(&block) }
|
220
|
-
else
|
221
|
-
while true
|
222
|
-
throttler.(&block)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
rescue LocalJumpError, StopIteration
|
226
|
-
# break called or StopIteration raised
|
227
|
-
end
|
228
|
-
|
229
|
-
private
|
230
|
-
|
231
|
-
# Helper method for performing a `cancel_after` with optional reset.
|
232
|
-
#
|
233
|
-
# @param interval [Number] timeout interval in seconds
|
234
|
-
# @param exception [Exception, Class, Array<class, message>] exception spec
|
235
|
-
# @return [any] block's return value
|
236
|
-
def cancel_after_with_optional_reset(interval, exception, &block)
|
237
|
-
fiber = Fiber.current
|
238
|
-
canceller = spin do
|
239
|
-
Polyphony.backend_sleep(interval)
|
240
|
-
exception = cancel_exception(exception)
|
241
|
-
exception.raising_fiber = Fiber.current
|
242
|
-
fiber.cancel(exception)
|
243
|
-
end
|
244
|
-
block.call(canceller)
|
245
|
-
ensure
|
246
|
-
canceller.stop
|
247
|
-
end
|
248
|
-
|
249
|
-
# Converts the given exception spec to an exception instance.
|
250
|
-
#
|
251
|
-
# @param exception [Exception, Class, Array<class, message>] exception spec
|
252
|
-
# @return [Exception] exception instance
|
253
|
-
def cancel_exception(exception)
|
254
|
-
case exception
|
255
|
-
when Class then exception.new
|
256
|
-
when Array then exception[0].new(exception[1])
|
257
|
-
else RuntimeError.new(exception)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
# Helper method for performing `#spin_loop` without throttling. Spins up a
|
262
|
-
# new fiber in which to run the loop.
|
263
|
-
#
|
264
|
-
# @param tag [any] new fiber's tag
|
265
|
-
# @param caller [Array<String>] caller info
|
266
|
-
# @param block [Proc] code to run
|
267
|
-
# @return [void]
|
268
|
-
def spin_loop_without_throttling(tag, caller, block)
|
269
|
-
Fiber.current.spin(tag, caller) do
|
270
|
-
block.call while true
|
271
|
-
rescue LocalJumpError, StopIteration
|
272
|
-
# break called or StopIteration raised
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
# Helper method for performing `#move_on_after` with optional reset.
|
277
|
-
#
|
278
|
-
# @param interval [Number] timeout interval in seconds
|
279
|
-
# @param value [any] return value in case of timeout
|
280
|
-
# @return [any] return value of given block or timeout value
|
281
|
-
def move_on_after_with_optional_reset(interval, value, &block)
|
282
|
-
fiber = Fiber.current
|
283
|
-
canceller = spin do
|
284
|
-
sleep interval
|
285
|
-
fiber.move_on(value)
|
286
|
-
end
|
287
|
-
block.call(canceller)
|
288
|
-
rescue Polyphony::MoveOn => e
|
289
|
-
e.value
|
290
|
-
ensure
|
291
|
-
canceller.stop
|
292
|
-
end
|
293
|
-
|
294
|
-
end
|
295
|
-
end
|
File without changes
|
File without changes
|
File without changes
|