Class: Concurrent::IVar
- Inherits:
-
Object
- Object
- Concurrent::IVar
- Includes:
- Obligation, Observable
- Defined in:
- lib/concurrent/ivar.rb
Overview
An IVar is like a future that you can assign. As a future is a value that is being computed that you can wait on, an IVar is a value that is waiting to be assigned, that you can wait on. IVars are single assignment and deterministic.
Then, express futures as an asynchronous computation that assigns an IVar. The IVar becomes the primitive on which [futures](Future) and [dataflow](Dataflow) are built.
An IVar is a single-element container that is normally created empty, and can only be set once. The I in IVar stands for immutable. Reading an IVar normally blocks until it is set. It is safe to set and read an IVar from different threads.
If you want to have some parallel task set the value in an IVar, you want a Future. If you want to create a graph of parallel tasks all executed when the values they depend on are ready you want dataflow. IVar is generally a low-level primitive.
**See Also:**
-
For the theory: Arvind, R. Nikhil, and K. Pingali. [I-Structures: Data structures for parallel computing](dl.acm.org/citation.cfm?id=69562). In Proceedings of Workshop on Graph Reduction, 1986.
-
For recent application: [DataDrivenFuture in Habanero Java from Rice](www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html).
Direct Known Subclasses
Instance Method Summary collapse
-
#add_observer(observer = nil, func = :update, &block) ⇒ Object
Add an observer on this object that will receive notification on update.
-
#fail(reason = StandardError.new) ⇒ Object
Set the
IVarto failed due to some error and wake or notify all threads waiting on it. -
#initialize(value = NO_VALUE, opts = {}) ⇒ IVar
constructor
Create a new
IVarin the:pendingstate with the (optional) initial value. -
#set(value) ⇒ Object
Set the
IVarto a value and wake or notify all threads waiting on it.
Methods included from Observable
#count_observers, #delete_observer, #delete_observers, #with_observer
Methods included from Obligation
#completed?, #exception, #fulfilled?, #incomplete?, #no_error!, #pending?, #reason, #rejected?, #state, #unscheduled?, #value, #value!, #wait
Methods included from Dereferenceable
Constructor Details
#initialize(value = NO_VALUE, opts = {}) ⇒ IVar
Create a new IVar in the :pending state with the (optional) initial value.
49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/concurrent/ivar.rb', line 49 def initialize(value = NO_VALUE, opts = {}) init_obligation self.observers = CopyOnWriteObserverSet.new (opts) if value == NO_VALUE @state = :pending else set(value) end end |
Instance Method Details
#add_observer(observer = nil, func = :update, &block) ⇒ Object
Add an observer on this object that will receive notification on update.
Upon completion the IVar will notify all observers in a thread-say way. The func method of the observer will be called with three arguments: the Time at which the Future completed the asynchronous operation, the final value (or nil on rejection), and the final reason (or nil on fulfillment).
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/concurrent/ivar.rb', line 70 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 mutex.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 |
#fail(reason = StandardError.new) ⇒ Object
Set the IVar to failed due to some error and wake or notify all threads waiting on it.
103 104 105 |
# File 'lib/concurrent/ivar.rb', line 103 def fail(reason = StandardError.new) complete(false, nil, reason) end |
#set(value) ⇒ Object
Set the IVar to a value and wake or notify all threads waiting on it.
95 96 97 |
# File 'lib/concurrent/ivar.rb', line 95 def set(value) complete(true, value, nil) end |