Class: Farce::Local::Lease

Inherits:
Abstract::Lease show all
Includes:
Scoped, Shareable::Unfreezable
Defined in:
lib/farce/local/lease.rb

Overview

A shareable lease with one independently initialized resource in each scope.

Examples:

Keeping an independent object in each Fiber

lease = Farce::Local::Lease.new(scope: :fiber) { { name: :initial } }
lease.checkout { |state| state[:name] = :parent }

Fiber.new do
  lease.checkout { |state| state[:name] = :child }
end.resume # => :child

lease.checkout { |state| state[:name] } # => :parent

Instance Attribute Summary

Attributes included from Scoped

#scope

Instance Method Summary collapse

Methods included from Shareable

#ractor_shareable?

Methods inherited from Abstract::Lease

#available?, #checked_out?, #checkin, #owned?, #retire, #retired?

Methods included from Internal::Noncopyable

#duplicable?

Constructor Details

#initialize(scope: :ractor) { ... } ⇒ Lease

Create a lease that initializes once on first use in each scope. Valid scopes are:

  • :ractor - The value is shared by all threads within the same Ractor.
  • :thread_group - The value is shared by all threads within the same thread group.
  • :thread - The value is shared by all fibers within the same thread.
  • :fiber_storage - The value is shared by all fibers using the same storage. Unless explicitly specified, storage is inherited from the parent fiber for blocking fibers, but not for non-blocking fibers (such as those created by Scheduler#schedule).
  • :fiber - Each fiber has its own independent value.

Parameters:

  • scope (Symbol) (defaults to: :ractor) —

    the scope of the lease

Yields:

  • builds the resource for each initialized scope

Yield Returns:

  • (BasicObject) —

    the initial resource for that scope

Raises:

  • (ArgumentError)


27
28
29
30
31
32
# File 'lib/farce/local/lease.rb', line 27

def initialize(scope: :ractor, &initializer)
  raise ArgumentError, "a resource constructor block is required" unless initializer

  @initializer = Ractor.shareable?(initializer) ? initializer : Ractor.shareable_proc(&initializer)
  super(scope:)
end

Instance Method Details

#checkout(timeout: nil) {|resource| ... } ⇒ BasicObject

Acquire the resource, waiting until it is available.

Parameters:

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

    maximum seconds to wait

Yield Parameters:

  • resource (BasicObject) —

    the acquired resource

Returns:

  • (BasicObject) —

    the resource without a block, or the block result

Raises:



35
36
37
38
39
40
41
42
# File 'lib/farce/local/lease.rb', line 35

def checkout(timeout: nil, &block)
  deadline = timeout_deadline(timeout)
  lease    = scoped_lease(timeout: remaining_timeout(deadline))
  raise TimeoutError, "lease checkout timed out" unless lease

  timeout = remaining_timeout(deadline)
  block ? lease.checkout(timeout:, &block) : lease.checkout(timeout:)
end

#try_checkout {|resource| ... } ⇒ BasicObject?

Acquire the resource immediately if it is available.

Yield Parameters:

  • resource (BasicObject) —

    the acquired resource

Returns:

  • (BasicObject, nil) —

    the resource or block result, or nil when unavailable

Raises:



45
46
47
48
49
50
# File 'lib/farce/local/lease.rb', line 45

def try_checkout(&block)
  lease = scoped_lease(wait: false)
  return unless lease

  block ? lease.try_checkout(&block) : lease.try_checkout
end