ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/atomic/AtomicIntegerArray.java
Revision: 1.1
Committed: Sat Mar 26 06:22:51 2016 UTC (8 years, 1 month ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7 package java.util.concurrent.atomic;
8
9 import java.util.function.IntBinaryOperator;
10 import java.util.function.IntUnaryOperator;
11
12 /**
13 * An {@code int} array in which elements may be updated atomically.
14 * See the {@link java.util.concurrent.atomic} package
15 * specification for description of the properties of atomic
16 * variables.
17 * @since 1.5
18 * @author Doug Lea
19 */
20 public class AtomicIntegerArray implements java.io.Serializable {
21 private static final long serialVersionUID = 2862133569453604235L;
22
23 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
24 private static final int ABASE;
25 private static final int ASHIFT;
26 private final int[] array;
27
28 static {
29 ABASE = U.arrayBaseOffset(int[].class);
30 int scale = U.arrayIndexScale(int[].class);
31 if ((scale & (scale - 1)) != 0)
32 throw new Error("array index scale not a power of two");
33 ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
34 }
35
36 private long checkedByteOffset(int i) {
37 if (i < 0 || i >= array.length)
38 throw new IndexOutOfBoundsException("index " + i);
39
40 return byteOffset(i);
41 }
42
43 private static long byteOffset(int i) {
44 return ((long) i << ASHIFT) + ABASE;
45 }
46
47 /**
48 * Creates a new AtomicIntegerArray of the given length, with all
49 * elements initially zero.
50 *
51 * @param length the length of the array
52 */
53 public AtomicIntegerArray(int length) {
54 array = new int[length];
55 }
56
57 /**
58 * Creates a new AtomicIntegerArray with the same length as, and
59 * all elements copied from, the given array.
60 *
61 * @param array the array to copy elements from
62 * @throws NullPointerException if array is null
63 */
64 public AtomicIntegerArray(int[] array) {
65 // Visibility guaranteed by final field guarantees
66 this.array = array.clone();
67 }
68
69 /**
70 * Returns the length of the array.
71 *
72 * @return the length of the array
73 */
74 public final int length() {
75 return array.length;
76 }
77
78 /**
79 * Gets the current value at position {@code i}.
80 *
81 * @param i the index
82 * @return the current value
83 */
84 public final int get(int i) {
85 return getRaw(checkedByteOffset(i));
86 }
87
88 private int getRaw(long offset) {
89 return U.getIntVolatile(array, offset);
90 }
91
92 /**
93 * Sets the element at position {@code i} to the given value.
94 *
95 * @param i the index
96 * @param newValue the new value
97 */
98 public final void set(int i, int newValue) {
99 U.putIntVolatile(array, checkedByteOffset(i), newValue);
100 }
101
102 /**
103 * Eventually sets the element at position {@code i} to the given value.
104 *
105 * @param i the index
106 * @param newValue the new value
107 * @since 1.6
108 */
109 public final void lazySet(int i, int newValue) {
110 U.putOrderedInt(array, checkedByteOffset(i), newValue);
111 }
112
113 /**
114 * Atomically sets the element at position {@code i} to the given
115 * value and returns the old value.
116 *
117 * @param i the index
118 * @param newValue the new value
119 * @return the previous value
120 */
121 public final int getAndSet(int i, int newValue) {
122 return U.getAndSetInt(array, checkedByteOffset(i), newValue);
123 }
124
125 /**
126 * Atomically sets the element at position {@code i} to the given
127 * updated value if the current value {@code ==} the expected value.
128 *
129 * @param i the index
130 * @param expect the expected value
131 * @param update the new value
132 * @return {@code true} if successful. False return indicates that
133 * the actual value was not equal to the expected value.
134 */
135 public final boolean compareAndSet(int i, int expect, int update) {
136 return compareAndSetRaw(checkedByteOffset(i), expect, update);
137 }
138
139 private boolean compareAndSetRaw(long offset, int expect, int update) {
140 return U.compareAndSwapInt(array, offset, expect, update);
141 }
142
143 /**
144 * Atomically sets the element at position {@code i} to the given
145 * updated value if the current value {@code ==} the expected value.
146 *
147 * <p><a href="package-summary.html#weakCompareAndSet">May fail
148 * spuriously and does not provide ordering guarantees</a>, so is
149 * only rarely an appropriate alternative to {@code compareAndSet}.
150 *
151 * @param i the index
152 * @param expect the expected value
153 * @param update the new value
154 * @return {@code true} if successful
155 */
156 public final boolean weakCompareAndSet(int i, int expect, int update) {
157 return compareAndSet(i, expect, update);
158 }
159
160 /**
161 * Atomically increments by one the element at index {@code i}.
162 *
163 * @param i the index
164 * @return the previous value
165 */
166 public final int getAndIncrement(int i) {
167 return getAndAdd(i, 1);
168 }
169
170 /**
171 * Atomically decrements by one the element at index {@code i}.
172 *
173 * @param i the index
174 * @return the previous value
175 */
176 public final int getAndDecrement(int i) {
177 return getAndAdd(i, -1);
178 }
179
180 /**
181 * Atomically adds the given value to the element at index {@code i}.
182 *
183 * @param i the index
184 * @param delta the value to add
185 * @return the previous value
186 */
187 public final int getAndAdd(int i, int delta) {
188 return U.getAndAddInt(array, checkedByteOffset(i), delta);
189 }
190
191 /**
192 * Atomically increments by one the element at index {@code i}.
193 *
194 * @param i the index
195 * @return the updated value
196 */
197 public final int incrementAndGet(int i) {
198 return getAndAdd(i, 1) + 1;
199 }
200
201 /**
202 * Atomically decrements by one the element at index {@code i}.
203 *
204 * @param i the index
205 * @return the updated value
206 */
207 public final int decrementAndGet(int i) {
208 return getAndAdd(i, -1) - 1;
209 }
210
211 /**
212 * Atomically adds the given value to the element at index {@code i}.
213 *
214 * @param i the index
215 * @param delta the value to add
216 * @return the updated value
217 */
218 public final int addAndGet(int i, int delta) {
219 return getAndAdd(i, delta) + delta;
220 }
221
222 /**
223 * Atomically updates the element at index {@code i} with the results
224 * of applying the given function, returning the previous value. The
225 * function should be side-effect-free, since it may be re-applied
226 * when attempted updates fail due to contention among threads.
227 *
228 * @param i the index
229 * @param updateFunction a side-effect-free function
230 * @return the previous value
231 * @since 1.8
232 */
233 public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
234 long offset = checkedByteOffset(i);
235 int prev, next;
236 do {
237 prev = getRaw(offset);
238 next = updateFunction.applyAsInt(prev);
239 } while (!compareAndSetRaw(offset, prev, next));
240 return prev;
241 }
242
243 /**
244 * Atomically updates the element at index {@code i} with the results
245 * of applying the given function, returning the updated value. The
246 * function should be side-effect-free, since it may be re-applied
247 * when attempted updates fail due to contention among threads.
248 *
249 * @param i the index
250 * @param updateFunction a side-effect-free function
251 * @return the updated value
252 * @since 1.8
253 */
254 public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
255 long offset = checkedByteOffset(i);
256 int prev, next;
257 do {
258 prev = getRaw(offset);
259 next = updateFunction.applyAsInt(prev);
260 } while (!compareAndSetRaw(offset, prev, next));
261 return next;
262 }
263
264 /**
265 * Atomically updates the element at index {@code i} with the
266 * results of applying the given function to the current and
267 * given values, returning the previous value. The function should
268 * be side-effect-free, since it may be re-applied when attempted
269 * updates fail due to contention among threads. The function is
270 * applied with the current value at index {@code i} as its first
271 * argument, and the given update as the second argument.
272 *
273 * @param i the index
274 * @param x the update value
275 * @param accumulatorFunction a side-effect-free function of two arguments
276 * @return the previous value
277 * @since 1.8
278 */
279 public final int getAndAccumulate(int i, int x,
280 IntBinaryOperator accumulatorFunction) {
281 long offset = checkedByteOffset(i);
282 int prev, next;
283 do {
284 prev = getRaw(offset);
285 next = accumulatorFunction.applyAsInt(prev, x);
286 } while (!compareAndSetRaw(offset, prev, next));
287 return prev;
288 }
289
290 /**
291 * Atomically updates the element at index {@code i} with the
292 * results of applying the given function to the current and
293 * given values, returning the updated value. The function should
294 * be side-effect-free, since it may be re-applied when attempted
295 * updates fail due to contention among threads. The function is
296 * applied with the current value at index {@code i} as its first
297 * argument, and the given update as the second argument.
298 *
299 * @param i the index
300 * @param x the update value
301 * @param accumulatorFunction a side-effect-free function of two arguments
302 * @return the updated value
303 * @since 1.8
304 */
305 public final int accumulateAndGet(int i, int x,
306 IntBinaryOperator accumulatorFunction) {
307 long offset = checkedByteOffset(i);
308 int prev, next;
309 do {
310 prev = getRaw(offset);
311 next = accumulatorFunction.applyAsInt(prev, x);
312 } while (!compareAndSetRaw(offset, prev, next));
313 return next;
314 }
315
316 /**
317 * Returns the String representation of the current values of array.
318 * @return the String representation of the current values of array
319 */
320 public String toString() {
321 int iMax = array.length - 1;
322 if (iMax == -1)
323 return "[]";
324
325 StringBuilder b = new StringBuilder();
326 b.append('[');
327 for (int i = 0; ; i++) {
328 b.append(getRaw(byteOffset(i)));
329 if (i == iMax)
330 return b.append(']').toString();
331 b.append(',').append(' ');
332 }
333 }
334
335 }