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.3
Committed: Mon Mar 4 16:09:25 2013 UTC (11 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +3 -3 lines
Log Message:
improve javadoc anchored text

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