Class: Garcon::Delay
- Includes:
- ExecutorOptions, Obligation
- Defined in:
- lib/garcon/task/delay.rb
Overview
The default behavior of ‘Delay` is to block indefinitely when calling either `value` or `wait`, executing the delayed operation on the current thread. This makes the `timeout` value completely irrelevant. To enable non-blocking behavior, use the `executor` constructor option. This will cause the delayed operation to be execute on the given executor, allowing the call to timeout.
Lazy evaluation of a block yielding an immutable result. Useful for expensive operations that may never be needed. It may be non-blocking, supports the ‘Obligation` interface, and accepts the injection of custom executor upon which to execute the block. Processing of block will be deferred until the first time `#value` is called. At that time the caller can choose to return immediately and let the block execute asynchronously, block indefinitely, or block with a timeout.
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.
‘Delay` includes the `Garcon::Dereferenceable` mixin to support thread safety of the reference returned by `#value`.
Instance Method Summary collapse
-
#initialize(opts = {}) { ... } ⇒ Delay
constructor
Create a new ‘Delay` in the `:pending` state.
-
#reconfigure { ... } ⇒ true, false
Reconfigures the block returning the value if still ‘#incomplete?`.
-
#value(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method.
-
#value!(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method.
-
#wait(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method.
Methods included from Obligation
#complete?, #exception, #fulfilled?, #incomplete?, #pending?, #reason, #rejected?, #state, #unscheduled?, #wait!
Constructor Details
#initialize(opts = {}) { ... } ⇒ Delay
Create a new ‘Delay` in the `:pending` state.
68 69 70 71 72 73 74 75 76 |
# File 'lib/garcon/task/delay.rb', line 68 def initialize(opts = {}, &block) raise ArgumentError, 'no block given' unless block_given? init_obligation (opts) @task_executor = get_executor_from(opts) @task = block @state = :pending @computing = false end |
Instance Method Details
#reconfigure { ... } ⇒ true, false
Reconfigures the block returning the value if still ‘#incomplete?`
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/garcon/task/delay.rb', line 158 def reconfigure(&block) mutex.lock raise ArgumentError.new('no block given') unless block_given? unless @computing @task = block true else false end ensure mutex.unlock end |
#value(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method. If the delayed operation raised an exception this method will return nil. The execption object can be accessed via the `#reason` method.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/garcon/task/delay.rb', line 88 def value(timeout = nil) if @task_executor super else mutex.synchronize do execute = @computing = true unless @computing if execute begin set_state(true, @task.call, nil) rescue => e set_state(false, nil, e) end end end if @do_nothing_on_deref @value else (@value) end end end |
#value!(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method. If the delayed operation raised an exception, this method will raise that exception (even when) the operation has already been executed).
123 124 125 126 127 128 129 130 131 |
# File 'lib/garcon/task/delay.rb', line 123 def value!(timeout = nil) if @task_executor super else result = value raise @reason if @reason result end end |
#wait(timeout = nil) ⇒ Object
Return the value this object represents after applying the options specified by the ‘#set_deref_options` method.
142 143 144 145 146 147 148 149 150 |
# File 'lib/garcon/task/delay.rb', line 142 def wait(timeout = nil) if @task_executor execute_task_once super(timeout) else value end self end |