class Concurrent::IVar
[DataDrivenFuture in Habanero Java from Rice](www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html).
2. For recent application:
In Proceedings of Workshop on Graph Reduction, 1986.
[I-Structures: Data structures for parallel computing](dl.acm.org/citation.cfm?id=69562).
1. For the theory: Arvind, R. Nikhil, and K. Pingali.
## See Also
“‘
ivar.set 2 # would now be an error
ivar.value #=> 14
ivar.set 14
ivar = Concurrent::IVar.new
“`ruby
Create, set and get an `IVar`
## Examples
generally a low-level primitive.
when the values they depend on are ready you want `dataflow`. `IVar` is
a `Future`. If you want to create a graph of parallel tasks all executed
If you want to have some parallel task set the value in an `IVar`, you want
from different threads.
`IVar` normally blocks until it is set. It is safe to set and read an `IVar`
can only be set once. The I in `IVar` stands for immutable. Reading an
An `IVar` is a single-element container that is normally created empty, and<br><br>(Dataflow) are built.
The `IVar` becomes the primitive on which [futures](Future) and
Then, express futures as an asynchronous computation that assigns an `IVar`.
deterministic.
to be assigned, that you can wait on. `IVars` are single assignment and
is being computed that you can wait on, an `IVar` is a value that is waiting
An `IVar` is like a future that you can assign. As a future is a value that
def add_observer(observer = nil, func = :update, &block)
-
func
(Symbol
) -- symbol naming the method to call when this -
observer
(Object
) -- the object that will be notified of changes
def add_observer(observer = nil, func = :update, &block) raise ArgumentError.new('cannot provide both an observer and a block') if observer && block direct_notification = false if block observer = block func = :call end synchronize do if event.set? direct_notification = true else observers.add_observer(observer, func) end end observer.send(func, Time.now, self.value, reason) if direct_notification observer end
def check_for_block_or_value!(block_given, value) # :nodoc:
@!visibility private
def check_for_block_or_value!(block_given, value) # :nodoc: if (block_given && value != NULL) || (! block_given && value == NULL) raise ArgumentError.new('must set with either a value or a block') end end
def complete(success, value, reason)
def complete(success, value, reason) complete_without_notification(success, value, reason) notify_observers(self.value, reason) self end
def complete_without_notification(success, value, reason)
def complete_without_notification(success, value, reason) synchronize { ns_complete_without_notification(success, value, reason) } self end
def fail(reason = StandardError.new)
-
(IVar)
- self
Raises:
-
(Concurrent::MultipleAssignmentError)
- if the `IVar` has already
Parameters:
-
reason
(Object
) -- for the failure
def fail(reason = StandardError.new) complete(false, nil, reason) end
def initialize(value = NULL, opts = {}, &block)
(**opts)
-
:copy_on_deref
(String
) -- call the given `Proc` passing -
:freeze_on_deref
(String
) -- call `#freeze` before -
:dup_on_deref
(String
) -- call `#dup` before returning
Parameters:
-
opts
(Hash
) -- the options to create a message with -
value
(Object
) -- the initial value
def initialize(value = NULL, opts = {}, &block) if value != NULL && block_given? raise ArgumentError.new('provide only a value or a block') end super(&nil) synchronize { ns_initialize(value, opts, &block) } end
def notify_observers(value, reason)
def notify_observers(value, reason) observers.notify_and_delete_observers{ [Time.now, value, reason] } end
def ns_complete_without_notification(success, value, reason)
def ns_complete_without_notification(success, value, reason) raise MultipleAssignmentError if [:fulfilled, :rejected].include? @state set_state(success, value, reason) event.set end
def ns_initialize(value, opts)
def ns_initialize(value, opts) value = yield if block_given? init_obligation self.observers = Collection::CopyOnWriteObserverSet.new set_deref_options(opts) @state = :pending if value != NULL ns_complete_without_notification(true, value, nil) end end
def safe_execute(task, args = [])
def safe_execute(task, args = []) if compare_and_set_state(:processing, :pending) success, val, reason = SafeTaskExecutor.new(task, rescue_exception: true).execute(*@args) complete(success, val, reason) yield(success, val, reason) if block_given? end end
def set(value = NULL)
-
(IVar)
- self
Raises:
-
(Concurrent::MultipleAssignmentError)
- if the `IVar` has already -
(ArgumentError)
- if both a value and a block are given
Other tags:
- Yield: - A block operation to use for setting the value
Parameters:
-
value
(Object
) -- the value to store in the `IVar`
def set(value = NULL) check_for_block_or_value!(block_given?, value) raise MultipleAssignmentError unless compare_and_set_state(:processing, :pending) begin value = yield if block_given? complete_without_notification(true, value, nil) rescue => ex complete_without_notification(false, nil, ex) end notify_observers(self.value, reason) self end
def try_set(value = NULL, &block)
-
(Boolean)
- true if the value was set else false
def try_set(value = NULL, &block) set(value, &block) true rescue MultipleAssignmentError false end