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)

Parameters:
  • 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:

: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)

@!visibility private
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)

@!visibility private
def complete_without_notification(success, value, reason)
  synchronize { ns_complete_without_notification(success, value, reason) }
  self
end

def fail(reason = StandardError.new)

Returns:
  • (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)

Options Hash: (**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)

@!visibility private
def notify_observers(value, reason)
  observers.notify_and_delete_observers{ [Time.now, value, reason] }
end

def ns_complete_without_notification(success, value, reason)

@!visibility private
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)

@!visibility private
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 = [])

@!visibility private
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)

Returns:
  • (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)

Returns:
  • (Boolean) - true if the value was set else false
def try_set(value = NULL, &block)
  set(value, &block)
  true
rescue MultipleAssignmentError
  false
end