ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk7/java/util/concurrent/atomic/AtomicLongArray.java
Revision: 1.4
Committed: Sun Jan 18 20:17:32 2015 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +1 -0 lines
Log Message:
exactly one blank line before and after package statements

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 sun.misc.Unsafe;
10
11 /**
12 * A {@code long} array in which elements may be updated atomically.
13 * See the {@link java.util.concurrent.atomic} package specification
14 * for description of the properties of atomic variables.
15 * @since 1.5
16 * @author Doug Lea
17 */
18 public class AtomicLongArray implements java.io.Serializable {
19 private static final long serialVersionUID = -2308431214976778248L;
20
21 private static final Unsafe unsafe = Unsafe.getUnsafe();
22 private static final int base = unsafe.arrayBaseOffset(long[].class);
23 private static final int shift;
24 private final long[] array;
25
26 static {
27 int scale = unsafe.arrayIndexScale(long[].class);
28 if ((scale & (scale - 1)) != 0)
29 throw new Error("data type scale not a power of two");
30 shift = 31 - Integer.numberOfLeadingZeros(scale);
31 }
32
33 private long checkedByteOffset(int i) {
34 if (i < 0 || i >= array.length)
35 throw new IndexOutOfBoundsException("index " + i);
36
37 return byteOffset(i);
38 }
39
40 private static long byteOffset(int i) {
41 return ((long) i << shift) + base;
42 }
43
44 /**
45 * Creates a new AtomicLongArray of the given length, with all
46 * elements initially zero.
47 *
48 * @param length the length of the array
49 */
50 public AtomicLongArray(int length) {
51 array = new long[length];
52 }
53
54 /**
55 * Creates a new AtomicLongArray with the same length as, and
56 * all elements copied from, the given array.
57 *
58 * @param array the array to copy elements from
59 * @throws NullPointerException if array is null
60 */
61 public AtomicLongArray(long[] array) {
62 // Visibility guaranteed by final field guarantees
63 this.array = array.clone();
64 }
65
66 /**
67 * Returns the length of the array.
68 *
69 * @return the length of the array
70 */
71 public final int length() {
72 return array.length;
73 }
74
75 /**
76 * Gets the current value at position {@code i}.
77 *
78 * @param i the index
79 * @return the current value
80 */
81 public final long get(int i) {
82 return getRaw(checkedByteOffset(i));
83 }
84
85 private long getRaw(long offset) {
86 return unsafe.getLongVolatile(array, offset);
87 }
88
89 /**
90 * Sets the element at position {@code i} to the given value.
91 *
92 * @param i the index
93 * @param newValue the new value
94 */
95 public final void set(int i, long newValue) {
96 unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
97 }
98
99 /**
100 * Eventually sets the element at position {@code i} to the given value.
101 *
102 * @param i the index
103 * @param newValue the new value
104 * @since 1.6
105 */
106 public final void lazySet(int i, long newValue) {
107 unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
108 }
109
110 /**
111 * Atomically sets the element at position {@code i} to the given value
112 * and returns the old value.
113 *
114 * @param i the index
115 * @param newValue the new value
116 * @return the previous value
117 */
118 public final long getAndSet(int i, long newValue) {
119 long offset = checkedByteOffset(i);
120 while (true) {
121 long current = getRaw(offset);
122 if (compareAndSetRaw(offset, current, newValue))
123 return current;
124 }
125 }
126
127 /**
128 * Atomically sets the element at position {@code i} to the given
129 * updated value if the current value {@code ==} the expected value.
130 *
131 * @param i the index
132 * @param expect the expected value
133 * @param update the new value
134 * @return true if successful. False return indicates that
135 * the actual value was not equal to the expected value.
136 */
137 public final boolean compareAndSet(int i, long expect, long update) {
138 return compareAndSetRaw(checkedByteOffset(i), expect, update);
139 }
140
141 private boolean compareAndSetRaw(long offset, long expect, long update) {
142 return unsafe.compareAndSwapLong(array, offset, expect, update);
143 }
144
145 /**
146 * Atomically sets the element at position {@code i} to the given
147 * updated value if the current value {@code ==} the expected value.
148 *
149 * <p><a href="package-summary.html#weakCompareAndSet">May fail
150 * spuriously and does not provide ordering guarantees</a>, so is
151 * only rarely an appropriate alternative to {@code compareAndSet}.
152 *
153 * @param i the index
154 * @param expect the expected value
155 * @param update the new value
156 * @return true if successful
157 */
158 public final boolean weakCompareAndSet(int i, long expect, long update) {
159 return compareAndSet(i, expect, update);
160 }
161
162 /**
163 * Atomically increments by one the element at index {@code i}.
164 *
165 * @param i the index
166 * @return the previous value
167 */
168 public final long getAndIncrement(int i) {
169 return getAndAdd(i, 1);
170 }
171
172 /**
173 * Atomically decrements by one the element at index {@code i}.
174 *
175 * @param i the index
176 * @return the previous value
177 */
178 public final long getAndDecrement(int i) {
179 return getAndAdd(i, -1);
180 }
181
182 /**
183 * Atomically adds the given value to the element at index {@code i}.
184 *
185 * @param i the index
186 * @param delta the value to add
187 * @return the previous value
188 */
189 public final long getAndAdd(int i, long delta) {
190 long offset = checkedByteOffset(i);
191 while (true) {
192 long current = getRaw(offset);
193 if (compareAndSetRaw(offset, current, current + delta))
194 return current;
195 }
196 }
197
198 /**
199 * Atomically increments by one the element at index {@code i}.
200 *
201 * @param i the index
202 * @return the updated value
203 */
204 public final long incrementAndGet(int i) {
205 return addAndGet(i, 1);
206 }
207
208 /**
209 * Atomically decrements by one the element at index {@code i}.
210 *
211 * @param i the index
212 * @return the updated value
213 */
214 public final long decrementAndGet(int i) {
215 return addAndGet(i, -1);
216 }
217
218 /**
219 * Atomically adds the given value to the element at index {@code i}.
220 *
221 * @param i the index
222 * @param delta the value to add
223 * @return the updated value
224 */
225 public long addAndGet(int i, long delta) {
226 long offset = checkedByteOffset(i);
227 while (true) {
228 long current = getRaw(offset);
229 long next = current + delta;
230 if (compareAndSetRaw(offset, current, next))
231 return next;
232 }
233 }
234
235 /**
236 * Returns the String representation of the current values of array.
237 * @return the String representation of the current values of array
238 */
239 public String toString() {
240 int iMax = array.length - 1;
241 if (iMax == -1)
242 return "[]";
243
244 StringBuilder b = new StringBuilder();
245 b.append('[');
246 for (int i = 0; ; i++) {
247 b.append(getRaw(byteOffset(i)));
248 if (i == iMax)
249 return b.append(']').toString();
250 b.append(',').append(' ');
251 }
252 }
253
254 }