Class: Object
- Inherits:
- BasicObject
- Defined in:
- lib/polyphony/extensions/object.rb
Overview
Object extensions (methods available to all objects / call sites)
Instance Method Summary collapse
-
#after(interval, &block) ⇒ Fiber
Spins up a fiber that will run the given block after sleeping for the given delay.
-
#cancel_after(interval, with_exception: Polyphony::Cancel, &block) ⇒ Object
Runs the given block after setting up a cancellation timer for cancellation.
-
#every(interval, &block) ⇒ Object
Runs the given block in an infinite loop with a regular interval between consecutive iterations.
-
#move_on_after(interval, with_value: nil, &block) ⇒ Object
Runs the given block after setting up a cancellation timer for cancellation.
-
#receive ⇒ any
Returns the first message from the current fiber's mailbox.
-
#receive_all_pending ⇒ Array
Returns all messages currently pending on the current fiber's mailbox.
-
#receive_loop(&block) ⇒ Object
Receives messages in an infinite loop from the current fiber's mailbox, passing them to the given block.
-
#sleep(duration = nil) ⇒ any
Sleeps for the given duration.
-
#spin(tag = nil, &block) ⇒ Fiber
Spins up a new fiber.
-
#spin_loop(tag = nil, rate: nil, interval: nil, &block) ⇒ Fiber
Spins up a new fiber, running the given block inside an infinite loop.
-
#spin_scope(&block) ⇒ any
Runs the given code, then waits for any child fibers of the current fibers to terminate.
-
#supervise(*args, **opts, &block) ⇒ any
Supervises the current fiber's children.
-
#throttled_loop(rate = nil, **opts, &block) ⇒ any
Starts a throttled loop with the given rate.
Instance Method Details
#after(interval, &block) ⇒ Fiber
Spins up a fiber that will run the given block after sleeping for the given delay.
12 13 14 15 16 17 |
# File 'lib/polyphony/extensions/object.rb', line 12 def after(interval, &block) spin do sleep interval block.() end end |
#cancel_after(interval) {|Fiber| ... } ⇒ any #cancel_after(interval, with_exception: exception) {|Fiber| ... } ⇒ any #cancel_after(interval, with_exception: [klass, message]) {|Fiber| ... } ⇒ any
Runs the given block after setting up a cancellation timer for
cancellation. If the cancellation timer elapses, the execution will be
interrupted with an exception defaulting to Polyphony::Cancel
.
This method should be used when a timeout should cause an exception to be propagated down the call stack or up the fiber tree.
Example of normal use:
def read_from_io_with_timeout(io) cancel_after(10) { io.read } rescue Polyphony::Cancel nil end
The timeout period can be reset by passing a block that takes a single
argument. The block will be provided with the canceller fiber. To reset
the timeout, use Fiber#reset
, as shown in the following example:
cancel_after(10) do |timeout| loop do msg = socket.gets timeout.reset handle_msg(msg) end end
60 61 62 63 64 65 66 |
# File 'lib/polyphony/extensions/object.rb', line 60 def cancel_after(interval, with_exception: Polyphony::Cancel, &block) if block.arity > 0 cancel_after_with_optional_reset(interval, with_exception, &block) else Polyphony.backend_timeout(interval, with_exception, &block) end end |
#every(interval, &block) ⇒ Object
Runs the given block in an infinite loop with a regular interval between consecutive iterations.
112 113 114 |
# File 'lib/polyphony/extensions/object.rb', line 112 def every(interval, &block) Polyphony.backend_timer_loop(interval, &block) end |
#move_on_after(interval) {|Fiber| ... } ⇒ any #move_on_after(interval, with_value: value) {|Fiber| ... } ⇒ any
Runs the given block after setting up a cancellation timer for
cancellation. If the cancellation timer elapses, the execution will be
interrupted with a Polyphony::MoveOn
exception, which will be rescued,
and with cause the operation to return the given value.
This method should be used when a timeout is to be handled locally, without generating an exception that is to propagated down the call stack or up the fiber tree.
Example of normal use:
move_on_after(10) { sleep 60 42 } #=> nil
move_on_after(10, with_value: :oops) { sleep 60 42 } #=> :oops
The timeout period can be reset by passing a block that takes a single
argument. The block will be provided with the canceller fiber. To reset
the timeout, use Fiber#reset
, as shown in the following example:
move_on_after(10) do |timeout| loop do msg = socket.gets timeout.reset handle_msg(msg) end end
158 159 160 161 162 163 164 |
# File 'lib/polyphony/extensions/object.rb', line 158 def move_on_after(interval, with_value: nil, &block) if block.arity > 0 move_on_after_with_optional_reset(interval, with_value, &block) else Polyphony.backend_timeout(interval, nil, with_value, &block) end end |
#receive ⇒ any
Returns the first message from the current fiber's mailbox. If the mailbox is empty, blocks until a message is available.
170 171 172 |
# File 'lib/polyphony/extensions/object.rb', line 170 def receive Fiber.current.receive end |
#receive_all_pending ⇒ Array
Returns all messages currently pending on the current fiber's mailbox.
183 184 185 |
# File 'lib/polyphony/extensions/object.rb', line 183 def receive_all_pending Fiber.current.receive_all_pending end |
#receive_loop(&block) ⇒ Object
Receives messages in an infinite loop from the current fiber's mailbox, passing them to the given block.
176 177 178 |
# File 'lib/polyphony/extensions/object.rb', line 176 def receive_loop(&block) Fiber.current.receive_loop(&block) end |
#sleep(duration = nil) ⇒ any
Sleeps for the given duration. If the duration is nil
, sleeps
indefinitely.
202 203 204 205 206 207 208 |
# File 'lib/polyphony/extensions/object.rb', line 202 def sleep(duration = nil) if duration Polyphony.backend_sleep(duration) else Polyphony.backend_wait_event(true) end end |
#spin(tag = nil, &block) ⇒ Fiber
Spins up a new fiber.
72 73 74 |
# File 'lib/polyphony/extensions/object.rb', line 72 def spin(tag = nil, &block) Fiber.current.spin(tag, caller, &block) end |
#spin_loop(tag = nil, rate: nil, interval: nil, &block) ⇒ Fiber
Spins up a new fiber, running the given block inside an infinite loop. If
rate:
or interval:
parameters are given, the loop is throttled
accordingly.
84 85 86 87 88 89 90 91 92 |
# File 'lib/polyphony/extensions/object.rb', line 84 def spin_loop(tag = nil, rate: nil, interval: nil, &block) if rate || interval Fiber.current.spin(tag, caller) do throttled_loop(rate:, interval:, &block) end else spin_loop_without_throttling(tag, caller, block) end end |
#spin_scope(&block) ⇒ any
Runs the given code, then waits for any child fibers of the current fibers to terminate.
98 99 100 101 102 103 104 105 106 |
# File 'lib/polyphony/extensions/object.rb', line 98 def spin_scope(&block) raise unless block spin do result = yield Fiber.current.await_all_children result end.await end |
#supervise(*args, **opts, &block) ⇒ any
Supervises the current fiber's children. See Fiber#supervise
for
options.
193 194 195 |
# File 'lib/polyphony/extensions/object.rb', line 193 def supervise(*args, **opts, &block) Fiber.current.supervise(*args, **opts, &block) end |
#throttled_loop(rate = nil, **opts, &block) ⇒ any
Starts a throttled loop with the given rate. If count:
is given, the
loop is run for the given number of times. Otherwise, the loop is
infinite. The loop rate (times per second) can be given as the rate
parameter. The throttling can also be controlled by providing an
interval:
or rate:
named parameter.
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/polyphony/extensions/object.rb', line 221 def throttled_loop(rate = nil, **opts, &block) throttler = Polyphony::Throttler.new(rate || opts) if opts[:count] opts[:count].times { |_i| throttler.(&block) } else throttler.(&block) while true end rescue LocalJumpError, StopIteration # break called or StopIteration raised end |