Class: LazyInit::LazyValue
- Inherits:
-
Object
- Object
- LazyInit::LazyValue
- Defined in:
- lib/lazy_init/lazy_value.rb
Overview
Thread-safe container for lazy-initialized values with performance-optimized access.
LazyValue provides a thread-safe wrapper around expensive computations that should only be executed once. It uses a double-checked locking pattern with an ultra-fast hot path that avoids synchronization overhead after initial computation.
The implementation separates the fast path (simple instance variable access) from the slow path (computation with full synchronization) for optimal performance in the common case where values are accessed repeatedly after computation.
Instance Method Summary collapse
-
#computed? ⇒ Boolean
Check if the value has been successfully computed.
-
#exception ⇒ Exception?
Access the cached exception if one exists.
-
#exception? ⇒ Boolean
Check if the computation resulted in a cached exception.
-
#initialize(timeout: nil, &block) ⇒ LazyValue
constructor
Create a new lazy value container.
-
#reset! ⇒ void
Reset the lazy value to its initial uncomputed state.
-
#value ⇒ Object
Get the computed value, executing the block if necessary.
Constructor Details
#initialize(timeout: nil, &block) ⇒ LazyValue
Create a new lazy value container.
The computation block will be executed at most once when value() is first called. Subsequent calls to value() return the cached result without re-executing the block.
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/lazy_init/lazy_value.rb', line 45 def initialize(timeout: nil, &block) raise ArgumentError, 'Block is required' unless block @block = block @timeout = timeout @mutex = Mutex.new @computed = false @value = nil @exception = nil end |
Instance Method Details
#computed? ⇒ Boolean
Check if the value has been successfully computed.
Returns false if computation hasn’t started, failed with an exception, or was reset. Only returns true for successful computations.
83 84 85 |
# File 'lib/lazy_init/lazy_value.rb', line 83 def computed? @computed && @exception.nil? end |
#exception ⇒ Exception?
Access the cached exception if one exists.
Returns the actual exception object that was raised during computation, or nil if no exception occurred or computation hasn’t been attempted.
117 118 119 |
# File 'lib/lazy_init/lazy_value.rb', line 117 def exception @mutex.synchronize { @exception } end |
#exception? ⇒ Boolean
Check if the computation resulted in a cached exception.
This method is thread-safe and can be used to determine if value() will raise an exception without actually triggering it.
107 108 109 |
# File 'lib/lazy_init/lazy_value.rb', line 107 def exception? @mutex.synchronize { !@exception.nil? } end |
#reset! ⇒ void
This method returns an undefined value.
Reset the lazy value to its initial uncomputed state.
Clears the cached value and any cached exceptions, allowing the computation to be re-executed on the next call to value(). This method is thread-safe.
93 94 95 96 97 98 99 |
# File 'lib/lazy_init/lazy_value.rb', line 93 def reset! @mutex.synchronize do @computed = false @value = nil @exception = nil end end |
#value ⇒ Object
Get the computed value, executing the block if necessary.
Uses an optimized double-checked locking pattern: the hot path (after computation) requires only a single instance variable check and direct return. The cold path (during computation) handles full synchronization and error management.
If the computation raises an exception, that exception is cached and re-raised on subsequent calls to maintain consistent behavior.
68 69 70 71 72 73 74 75 |
# File 'lib/lazy_init/lazy_value.rb', line 68 def value # hot path: optimized for repeated access after computation # this should be nearly as fast as direct instance variable access return @value if @computed # cold path: handle computation and synchronization compute_or_raise_exception end |