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

Instance Method Details

#after(interval, &block) ⇒ Fiber

Spins up a fiber that will run the given block after sleeping for the given delay.

Parameters:

  • interval (Number)

    delay in seconds before running the given block

Returns:



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

Overloads:

  • #cancel_after(interval) {|Fiber| ... } ⇒ any

    Returns block's return value.

    Parameters:

    • interval (Number)

      timout in seconds

    Yields:

    • (Fiber)

      timeout fiber

    Returns:

    • (any)

      block's return value

  • #cancel_after(interval, with_exception: exception) {|Fiber| ... } ⇒ any

    Returns block's return value.

    Parameters:

    • interval (Number)

      timout in seconds

    • with_exception (Class, Exception) (defaults to: exception)

      exception or exception class

    Yields:

    • (Fiber)

      timeout fiber

    Returns:

    • (any)

      block's return value

  • #cancel_after(interval, with_exception: [klass, message]) {|Fiber| ... } ⇒ any

    Returns block's return value.

    Parameters:

    • interval (Number)

      timout in seconds

    • with_exception (Array) (defaults to: [klass, message])

      array containing class and message to use as exception

    Yields:

    • (Fiber)

      timeout fiber

    Returns:

    • (any)

      block's return value



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.

Parameters:

  • interval (Number)

    interval between consecutive iterations in seconds



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

Overloads:

  • #move_on_after(interval) {|Fiber| ... } ⇒ any

    Returns block's return value.

    Parameters:

    • interval (Number)

      timout in seconds

    Yields:

    • (Fiber)

      timeout fiber

    Returns:

    • (any)

      block's return value

  • #move_on_after(interval, with_value: value) {|Fiber| ... } ⇒ any

    Returns block's return value.

    Parameters:

    • interval (Number)

      timout in seconds

    • with_value (any) (defaults to: value)

      return value in case of timeout

    Yields:

    • (Fiber)

      timeout fiber

    Returns:

    • (any)

      block's return value



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

#receiveany

Returns the first message from the current fiber's mailbox. If the mailbox is empty, blocks until a message is available.

Returns:

  • (any)

    received message



170
171
172
# File 'lib/polyphony/extensions/object.rb', line 170

def receive
  Fiber.current.receive
end

#receive_all_pendingArray

Returns all messages currently pending on the current fiber's mailbox.

Returns:

  • (Array)

    array of received messages



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.

Parameters:

  • duration (Number, nil) (defaults to: nil)

    duration

Returns:

  • (any)


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.

Parameters:

  • tag (any) (defaults to: nil)

    optional tag for the new fiber

Returns:



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.

Parameters:

  • tag (any) (defaults to: nil)

    optional tag for the new fiber

  • rate (Number, nil) (defaults to: nil)

    loop rate (times per second)

  • interval (Number, nil) (defaults to: nil)

    interval between consecutive iterations in seconds

Returns:



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.

Returns:

  • (any)

    given block's return value



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.

Parameters:

  • args (Array)

    positional parameters

  • opts (Hash)

    named parameters

Returns:

  • (any)


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.

Parameters:

  • rate (Number, nil) (defaults to: nil)

    loop rate (times per second)

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :rate (Number)

    loop rate (times per second)

  • :interval (Number)

    loop interval in seconds

  • :count (Number)

    number of iterations (nil for infinite)

Returns:

  • (any)


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