|
45 | 45 | * <p> |
46 | 46 | * A {@linkplain StableValue {@code StableValue<T>}} is created using the factory method |
47 | 47 | * {@linkplain StableValue#empty() {@code StableValue.empty()}}. When created, the |
48 | | - * stable value is <em>unset</em>, which means it holds no value. It's holder value of |
49 | | - * type {@code T} can be <em>set</em> by passing a value via |
| 48 | + * stable value is <em>unset</em>, which means it holds no value. Its holder value, of |
| 49 | + * type {@code T}, can be <em>set</em> by calling |
50 | 50 | * {@linkplain #trySet(Object) trySet()}, {@linkplain #setOrThrow(Object) setOrThrow()}, |
51 | | - * or {@linkplain #computeIfUnset(Supplier) computeIfUnset()}. Once set, the value held |
52 | | - * by a {@code StableValue} can never change and can be retrieved by calling |
| 51 | + * or {@linkplain #computeIfUnset(Supplier) computeIfUnset()}. Once set, the holder value |
| 52 | + * can never change and can be retrieved by calling |
53 | 53 | * {@linkplain #orElseThrow() orElseThrow()}, {@linkplain #orElse(Object) orElse()}, or |
54 | 54 | * {@linkplain #computeIfUnset(Supplier) computeIfUnset()}. |
55 | 55 | * <p> |
56 | | - * A stable value that is <em>set</em> is treated as a constant by the JVM, enabling |
57 | | - * the same performance optimizations that are possible by marking a field {@code final}. |
58 | | - * Yet, stable values offer greater flexibility as to the timing of initialization |
| 56 | + * A stable value that is <em>set</em> is treated as a constant by the JVM, enabling the |
| 57 | + * same performance optimizations that are available for {@code final} fields. |
| 58 | + * As such, stable values can be used to replace {@code final} fields in cases where |
| 59 | + * <em>at-most-once</em> update semantics is crucial, but where the eager initialization semantics |
| 60 | + * associated with {@code final} fields is too restrictive. |
59 | 61 | * <p> |
60 | 62 | * Consider the following example where a stable value field "{@code logger}" is an |
61 | 63 | * immutable holder of a value of type {@code Logger} and that is initially created |
|
86 | 88 | * <p> |
87 | 89 | * Note that the holder value can only be set at most once. |
88 | 90 | * <p> |
89 | | - * To guarantee that only one instance of {@code Logger} instance is ever created, the |
90 | | - * {@linkplain #computeIfUnset(Supplier) computeIfUnset()} method can be used instead as |
91 | | - * shown in this improved example, where the holder is atomically and lazily computed via |
92 | | - * a lambda expression: |
| 91 | + * To guarantee that, even under races, only one instance of {@code Logger} is ever created, the |
| 92 | + * {@linkplain #computeIfUnset(Supplier) computeIfUnset()} method can be used instead, |
| 93 | + * where the holder is atomically and lazily computed via a lambda expression: |
93 | 94 | * |
94 | 95 | * {@snippet lang = java: |
95 | 96 | * class Component { |
|
115 | 116 | * returned to the client. In other words, {@code computeIfUnset()} guarantees that a |
116 | 117 | * stable value's holder value is <em>set</em> before it is used. |
117 | 118 | * <p> |
118 | | - * Even though the stable value, once <em>set</em>, is immutable, its holder value is not |
119 | | - * required to be <em>set</em> upfront. Rather, it can be <em>set</em> on demand. |
120 | 119 | * Furthermore, {@code computeIfUnset()} guarantees that the lambda expression provided is |
121 | 120 | * evaluated only once, even when {@code logger.computeIfUnset()} is invoked concurrently. |
122 | 121 | * This property is crucial as evaluation of the lambda expression may have side effects, |
|
126 | 125 | * <h2 id="stable-functions">Stable Functions</h2> |
127 | 126 | * Stable values provide the foundation for higher-level functional abstractions. A |
128 | 127 | * <em>stable supplier</em> is a supplier that computes a value and then caches it into |
129 | | - * a backing stable value storage for later use. A stable supplier is created -- via the |
130 | | - * {@linkplain StableValue#ofSupplier(Supplier) StableValue.ofSupplier()} factory -- |
| 128 | + * a backing stable value storage for later use. A stable supplier is created via the |
| 129 | + * {@linkplain StableValue#ofSupplier(Supplier) StableValue.ofSupplier()} factory, |
131 | 130 | * by providing an original {@linkplain Supplier} which is invoked when the |
132 | 131 | * stable supplier is first accessed: |
133 | 132 | * |
|
144 | 143 | * } |
145 | 144 | * } |
146 | 145 | *} |
147 | | - * This also allows the stable supplier to be accessed directly, without going through |
148 | | - * an accessor method like {@code getLogger()} in the previous example. |
| 146 | + * A stable supplier encapsulates access to its backing stable value storage. This means that |
| 147 | + * code inside {@code Component} can obtain the logger object directly from the stable supplier, |
| 148 | + * without having to go through an accessor method like {@code getLogger()}. |
149 | 149 | * <p> |
150 | 150 | * A <em>stable int function</em> is a function that takes an {@code int} parameter and |
151 | 151 | * uses it to compute a result that is then cached into the backing stable value storage |
152 | | - * for that parameter value. When the stable int function is first created -- via the |
| 152 | + * for that parameter value. A stable int function is created via the |
153 | 153 | * {@linkplain StableValue#ofIntFunction(int, IntFunction) StableValue.ofIntFunction()} |
154 | | - * factory -- the input range (i.e. [0, size)) is specified together with an original |
| 154 | + * factory. Upon creation, the input range (i.e. [0, size)) is specified together with an original |
155 | 155 | * {@linkplain IntFunction} which is invoked at most once per input value. In effect, |
156 | 156 | * the stable int function will act like a cache for the original {@linkplain IntFunction}: |
157 | 157 | * |
|
171 | 171 | * <p> |
172 | 172 | * A <em>stable function</em> is a function that takes a parameter (of type {@code T}) and |
173 | 173 | * uses it to compute a result that is then cached into the backing stable value storage |
174 | | - * for that parameter value. When the stable function is first created -- via the |
175 | | - * {@linkplain StableValue#ofFunction(Set, Function) StableValue.ofFunction()} factory -- |
176 | | - * the input {@linkplain Set} is specified together with an original {@linkplain Function} |
| 174 | + * for that parameter value. A stable function is created via the |
| 175 | + * {@linkplain StableValue#ofFunction(Set, Function) StableValue.ofFunction()} factory. |
| 176 | + * Upon creation, the input {@linkplain Set} is specified together with an original {@linkplain Function} |
177 | 177 | * which is invoked at most once per input value. In effect, the stable function will act |
178 | 178 | * like a cache for the original {@linkplain Function}: |
179 | 179 | * |
|
193 | 193 | * |
194 | 194 | * <h2 id="stable-collections">Stable Collections</h2> |
195 | 195 | * Stable values can also be used as backing storage for immutable collections. |
196 | | - * A <em>stable list</em> is an immutable list of fixed size, backed by an array of |
| 196 | + * A <em>stable list</em> is an immutable list, backed by an array of |
197 | 197 | * stable values. The stable list elements are computed when they are first accessed, |
198 | 198 | * using a provided {@linkplain IntFunction}: |
199 | 199 | * |
|
233 | 233 | * } |
234 | 234 | *} |
235 | 235 | * <h2 id="thread-safety">Thread Safety</h2> |
236 | | - * A holder value is guaranteed to only be settable at most once. If competing threads are |
237 | | - * racing to set a holder value, only the first is accepted and the other threads are |
238 | | - * blocked until the holder value is set. |
| 236 | + * A holder value is guaranteed to be set at most once. If competing threads are |
| 237 | + * racing to set a stable value, only one update succeeds, while other updates are |
| 238 | + * blocked until the stable value becomes set. |
239 | 239 | * <p> |
240 | 240 | * Updates to an object |
241 | 241 | * <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a> |
|
0 commit comments