Class: Farce::Exchanger

Inherits:
Abstract::Exchanger show all
Includes:
Shareable::Unfreezable
Defined in:
lib/farce/exchanger.rb

Overview

A Ractor-shareable rendezvous with transfer modes for unshareable values. Values received from a partner are automatically unwrapped.

Examples:

Exchanging mutable values between Ractors

exchanger = Farce::Exchanger.new
worker    = Farce::Ractor.new(exchanger) { |shared| shared.exchange([:worker]) }
exchanger.exchange([:main]) # => [:worker]

Instance Method Summary collapse

Methods included from Shareable

#ractor_shareable?

Methods included from Internal::Noncopyable

#duplicable?

Constructor Details

#initialize(mode: :copy) ⇒ Exchanger

Valid modes are:

  • :copy - The value will be copied between Ractors. This is the default mode.
  • :make_shareable - The value will be made Ractor-shareable using Ractor.make_shareable.
  • :move - The value will be moved between Ractors. This saves memory compared to copying, and supports values that can't be copied but moved (like IO objects). However, the value will no longer be accessible on the Ractor that pushed it.
  • :mutable - A Mutable instance will be created for the value. This isn't done recursively and thus will fail for nested unshareable values.
  • :local - The value will be kept local to the Ractor that pushed it. Another ractor trying to receive it will get an error. Useful for usage contained within a single Ractor.
  • :proxy - The value will be wrapped in a Farce::Proxy that executes calls in the original Ractor.
  • :raise - An error will be raised if the value is not Ractor-shareable. Useful for enforcing shareability.
  • :dedup - The value will be deduplicated using Farce.dedup, then made Ractor-shareable. This may update and freeze the original. Already-shareable values pass through unchanged.
  • :shareable_copy - The value will be copied and the copy will be made Ractor-shareable.

Parameters:

  • mode (Symbol) (defaults to: :copy) —

    the default mode used to transfer values between Ractors



18
19
20
21
22
# File 'lib/farce/exchanger.rb', line 18

def initialize(mode: :copy)
  @manager   = ModeManager.new(mode:)
  @exchanger = Internal::Exchanger.new
  super()
end

Instance Method Details

#exchange(offered, timeout: nil, mode: nil) { ... } ⇒ BasicObject?

Wait for a partner and return the partner's value. Offering nil allows a caller to receive a value without sending a payload. A timeout of zero only exchanges with a partner that is already waiting. A successful exchange of nil does not invoke the fallback.

The offered value is prepared before waiting. A timeout does not undo copying, moving, or freezing it. The fallback result is returned unchanged. Valid modes are:

  • :copy - The value will be copied between Ractors. This is the default mode.
  • :make_shareable - The value will be made Ractor-shareable using Ractor.make_shareable.
  • :move - The value will be moved between Ractors. This saves memory compared to copying, and supports values that can't be copied but moved (like IO objects). However, the value will no longer be accessible on the Ractor that pushed it.
  • :mutable - A Mutable instance will be created for the value. This isn't done recursively and thus will fail for nested unshareable values.
  • :local - The value will be kept local to the Ractor that pushed it. Another ractor trying to receive it will get an error. Useful for usage contained within a single Ractor.
  • :proxy - The value will be wrapped in a Farce::Proxy that executes calls in the original Ractor.
  • :raise - An error will be raised if the value is not Ractor-shareable. Useful for enforcing shareability.
  • :dedup - The value will be deduplicated using Farce.dedup, then made Ractor-shareable. This may update and freeze the original. Already-shareable values pass through unchanged.
  • :shareable_copy - The value will be copied and the copy will be made Ractor-shareable.

Parameters:

  • offered (BasicObject, nil) —

    the value to give to the partner

  • timeout (Numeric, nil) (defaults to: nil) —

    the maximum seconds to wait, or nil to wait indefinitely

  • mode (Symbol, nil) (defaults to: nil) —

    the transfer mode, or nil to use the exchanger's default mode

Yields:

  • called without arguments when the timeout expires

Returns:

  • (BasicObject, nil) —

    the partner's value, or the fallback result or nil on timeout

Raises:

  • (ArgumentError) —

    if the timeout is negative or not finite



33
34
35
36
37
38
39
# File 'lib/farce/exchanger.rb', line 33

def exchange(offered, timeout: nil, mode: nil)
  offered   = @manager.wrap(offered, mode:)
  timed_out = false
  result    = @exchanger.exchange(offered, timeout:) { timed_out = true }
  return @manager.unwrap(result) unless timed_out
  yield if block_given?
end

#mode ⇒ Symbol

The default mode used to transfer values between Ractors.

Returns:

  • (Symbol)


26
# File 'lib/farce/exchanger.rb', line 26

def mode = @manager.mode