|
5 | 5 |
|
6 | 6 | module Concurrent
|
7 | 7 |
|
| 8 | + # An `IVar` is a single-element container that is normally created empty, and |
| 9 | + # can only be set once. The I in `IVar` stands for immutable. Reading an `IVar` |
| 10 | + # normally blocks until it is set. It is safe to set and read an `IVar` from |
| 11 | + # different threads. |
| 12 | + # |
| 13 | + # If you want to have some parallel task set the value in an `IVar`, you want |
| 14 | + # a `Future`. If you want to create a graph of parallel tasks all executed when |
| 15 | + # the values they depend on are ready you want `dataflow`. `IVar` is generally |
| 16 | + # a low-level primitive. |
| 17 | + # |
| 18 | + # @example Create, set and get an `IVar` |
| 19 | + # ivar = Concurrent::IVar.new |
| 20 | + # ivar.set 14 |
| 21 | + # ivar.get #=> 14 |
| 22 | + # ivar.set 2 # would now be an error |
8 | 23 | class IVar
|
| 24 | + |
| 25 | + # Error that indicates that an `IVar` was set twice. Each `IVar` can only |
| 26 | + # be set once - they are immutable. |
9 | 27 | MultipleAssignmentError = Class.new(StandardError)
|
10 | 28 |
|
11 | 29 | include Obligation
|
12 |
| - include Concurrent::Observable |
| 30 | + include Observable |
13 | 31 |
|
14 |
| - NO_VALUE = Object.new |
| 32 | + # @!visibility private |
| 33 | + NO_VALUE = Object.new # :nodoc: |
15 | 34 |
|
16 |
| - # Create a new `Ivar` in the `:pending` state with the (optional) initial value. |
| 35 | + # Create a new `IVar` in the `:pending` state with the (optional) initial value. |
17 | 36 | #
|
18 | 37 | # @param [Object] value the initial value
|
19 | 38 | # @param [Hash] opts the options to create a message with
|
@@ -63,15 +82,22 @@ def add_observer(observer = nil, func = :update, &block)
|
63 | 82 | observer
|
64 | 83 | end
|
65 | 84 |
|
| 85 | + # Set the `IVar` to a value and wake or notify all threads waiting on it. |
| 86 | + # @param [Object] the value to store in the `IVar` |
| 87 | + # @raise [MultipleAssignmentError] if the `IVar` has already been set or otherwise completed |
66 | 88 | def set(value)
|
67 | 89 | complete(true, value, nil)
|
68 | 90 | end
|
69 | 91 |
|
| 92 | + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. |
| 93 | + # @option [Object] reason for the failure |
| 94 | + # @raise [MultipleAssignmentError] if the `IVar` has already been set or otherwise completed |
70 | 95 | def fail(reason = StandardError.new)
|
71 | 96 | complete(false, nil, reason)
|
72 | 97 | end
|
73 | 98 |
|
74 |
| - def complete(success, value, reason) |
| 99 | + # @!visibility private |
| 100 | + def complete(success, value, reason) # :nodoc: |
75 | 101 | mutex.synchronize do
|
76 | 102 | raise MultipleAssignmentError.new('multiple assignment') if [:fulfilled, :rejected].include? @state
|
77 | 103 | set_state(success, value, reason)
|
|
0 commit comments