Class: Functional::Delay

Inherits:
Synchronization::Object
  • Object
show all
Defined in:
lib/functional/delay.rb

Overview

Lazy evaluation of a block yielding an immutable result. Useful for expensive operations that may never be needed.

When a ‘Delay` is created its state is set to `pending`. The value and reason are both `nil`. The first time the `#value` method is called the enclosed opration will be run and the calling thread will block. Other threads attempting to call `#value` will block as well. Once the operation is complete the value will be set to the result of the operation or the reason will be set to the raised exception, as appropriate. All threads blocked on `#value` will return. Subsequent calls to `#value` will immediately return the cached value. The operation will only be run once. This means that any side effects created by the operation will only happen once as well.

See Also:

Instance Method Summary collapse

Constructor Details

#initialize { ... } ⇒ Delay

Create a new ‘Delay` in the `:pending` state.

Yields:

  • the delayed operation to perform

Raises:

  • (ArgumentError)

    if no block is given



29
30
31
32
33
34
35
36
# File 'lib/functional/delay.rb', line 29

def initialize(&block)
  raise ArgumentError.new('no block given') unless block_given?
  super
  synchronize do
    @state = :pending
    @task  = block
  end
end

Instance Method Details

#fulfilled?Boolean Also known as: value?

Has the delay been fulfilled?

Returns:

  • (Boolean)


73
74
75
# File 'lib/functional/delay.rb', line 73

def fulfilled?
  synchronize{ @state == :fulfilled }
end

#pending?Boolean

Is delay completion still pending?

Returns:

  • (Boolean)


87
88
89
# File 'lib/functional/delay.rb', line 87

def pending?
  synchronize{ @state == :pending }
end

#reasonStandardError

The exception raised when processing the block. Returns ‘nil` if the operation is still `:pending` or has been `:fulfilled`.

Returns:

  • (StandardError)

    the exception raised when processing the block else nil.



50
51
52
# File 'lib/functional/delay.rb', line 50

def reason
  synchronize{ @reason }
end

#rejected?Boolean Also known as: reason?

Has the delay been rejected?

Returns:

  • (Boolean)


80
81
82
# File 'lib/functional/delay.rb', line 80

def rejected?
  synchronize{ @state == :rejected }
end

#stateSymbol

Current state of block processing.

Returns:

  • (Symbol)

    the current state of block processing



41
42
43
# File 'lib/functional/delay.rb', line 41

def state
  synchronize{ @state }
end

#valueObject

Return the (possibly memoized) value of the delayed operation.

If the state is ‘:pending` then the calling thread will block while the operation is performed. All other threads simultaneously calling `#value` will block as well. Once the operation is complete (either `:fulfilled` or `:rejected`) all waiting threads will unblock and the new value will be returned.

If the state is not ‘:pending` when `#value` is called the (possibly memoized) value will be returned without blocking and without performing the operation again.

Returns:

  • (Object)

    the (possibly memoized) result of the block operation



67
68
69
# File 'lib/functional/delay.rb', line 67

def value
  synchronize{ execute_task_once }
end