Showing the changes to java/pkg/java/util/concurrent/atomic (32 of 18352 files). Show all
Unified · Split
Binary file not shown.
| @@ -0,0 +1,164 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * A {@code boolean} value that may be updated atomically. See the | |
| 41 | + * {@link java.util.concurrent.atomic} package specification for | |
| 42 | + * description of the properties of atomic variables. An | |
| 43 | + * {@code AtomicBoolean} is used in applications such as atomically | |
| 44 | + * updated flags, and cannot be used as a replacement for a | |
| 45 | + * {@link java.lang.Boolean}. | |
| 46 | + * | |
| 47 | + * @since 1.5 | |
| 48 | + * @author Doug Lea | |
| 49 | + */ | |
| 50 | +public class AtomicBoolean implements java.io.Serializable { | |
| 51 | + private static final long serialVersionUID = 4654671469794556979L; | |
| 52 | + // setup to use Unsafe.compareAndSwapInt for updates | |
| 53 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 54 | + private static final long valueOffset; | |
| 55 | + | |
| 56 | + static { | |
| 57 | + try { | |
| 58 | + valueOffset = unsafe.objectFieldOffset | |
| 59 | + (AtomicBoolean.class.getDeclaredField("value")); | |
| 60 | + } catch (Exception ex) { throw new Error(ex); } | |
| 61 | + } | |
| 62 | + | |
| 63 | + private volatile int value; | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * Creates a new {@code AtomicBoolean} with the given initial value. | |
| 67 | + * | |
| 68 | + * @param initialValue the initial value | |
| 69 | + */ | |
| 70 | + public AtomicBoolean(boolean initialValue) { | |
| 71 | + value = initialValue ? 1 : 0; | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * Creates a new {@code AtomicBoolean} with initial value {@code false}. | |
| 76 | + */ | |
| 77 | + public AtomicBoolean() { | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * Returns the current value. | |
| 82 | + * | |
| 83 | + * @return the current value | |
| 84 | + */ | |
| 85 | + public final boolean get() { | |
| 86 | + return value != 0; | |
| 87 | + } | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Atomically sets the value to the given updated value | |
| 91 | + * if the current value {@code ==} the expected value. | |
| 92 | + * | |
| 93 | + * @param expect the expected value | |
| 94 | + * @param update the new value | |
| 95 | + * @return true if successful. False return indicates that | |
| 96 | + * the actual value was not equal to the expected value. | |
| 97 | + */ | |
| 98 | + public final boolean compareAndSet(boolean expect, boolean update) { | |
| 99 | + int e = expect ? 1 : 0; | |
| 100 | + int u = update ? 1 : 0; | |
| 101 | + return unsafe.compareAndSwapInt(this, valueOffset, e, u); | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * Atomically sets the value to the given updated value | |
| 106 | + * if the current value {@code ==} the expected value. | |
| 107 | + * | |
| 108 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 109 | + * and does not provide ordering guarantees, so is only rarely an | |
| 110 | + * appropriate alternative to {@code compareAndSet}. | |
| 111 | + * | |
| 112 | + * @param expect the expected value | |
| 113 | + * @param update the new value | |
| 114 | + * @return true if successful. | |
| 115 | + */ | |
| 116 | + public boolean weakCompareAndSet(boolean expect, boolean update) { | |
| 117 | + int e = expect ? 1 : 0; | |
| 118 | + int u = update ? 1 : 0; | |
| 119 | + return unsafe.compareAndSwapInt(this, valueOffset, e, u); | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * Unconditionally sets to the given value. | |
| 124 | + * | |
| 125 | + * @param newValue the new value | |
| 126 | + */ | |
| 127 | + public final void set(boolean newValue) { | |
| 128 | + value = newValue ? 1 : 0; | |
| 129 | + } | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Eventually sets to the given value. | |
| 133 | + * | |
| 134 | + * @param newValue the new value | |
| 135 | + * @since 1.6 | |
| 136 | + */ | |
| 137 | + public final void lazySet(boolean newValue) { | |
| 138 | + int v = newValue ? 1 : 0; | |
| 139 | + unsafe.putOrderedInt(this, valueOffset, v); | |
| 140 | + } | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * Atomically sets to the given value and returns the previous value. | |
| 144 | + * | |
| 145 | + * @param newValue the new value | |
| 146 | + * @return the previous value | |
| 147 | + */ | |
| 148 | + public final boolean getAndSet(boolean newValue) { | |
| 149 | + for (;;) { | |
| 150 | + boolean current = get(); | |
| 151 | + if (compareAndSet(current, newValue)) | |
| 152 | + return current; | |
| 153 | + } | |
| 154 | + } | |
| 155 | + | |
| 156 | + /** | |
| 157 | + * Returns the String representation of the current value. | |
| 158 | + * @return the String representation of the current value. | |
| 159 | + */ | |
| 160 | + public String toString() { | |
| 161 | + return Boolean.toString(get()); | |
| 162 | + } | |
| 163 | + | |
| 164 | +} | |
Binary file not shown.
| @@ -0,0 +1,265 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * An {@code int} value that may be updated atomically. See the | |
| 41 | + * {@link java.util.concurrent.atomic} package specification for | |
| 42 | + * description of the properties of atomic variables. An | |
| 43 | + * {@code AtomicInteger} is used in applications such as atomically | |
| 44 | + * incremented counters, and cannot be used as a replacement for an | |
| 45 | + * {@link java.lang.Integer}. However, this class does extend | |
| 46 | + * {@code Number} to allow uniform access by tools and utilities that | |
| 47 | + * deal with numerically-based classes. | |
| 48 | + * | |
| 49 | + * @since 1.5 | |
| 50 | + * @author Doug Lea | |
| 51 | +*/ | |
| 52 | +public class AtomicInteger extends Number implements java.io.Serializable { | |
| 53 | + private static final long serialVersionUID = 6214790243416807050L; | |
| 54 | + | |
| 55 | + // setup to use Unsafe.compareAndSwapInt for updates | |
| 56 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 57 | + private static final long valueOffset; | |
| 58 | + | |
| 59 | + static { | |
| 60 | + try { | |
| 61 | + valueOffset = unsafe.objectFieldOffset | |
| 62 | + (AtomicInteger.class.getDeclaredField("value")); | |
| 63 | + } catch (Exception ex) { throw new Error(ex); } | |
| 64 | + } | |
| 65 | + | |
| 66 | + private volatile int value; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * Creates a new AtomicInteger with the given initial value. | |
| 70 | + * | |
| 71 | + * @param initialValue the initial value | |
| 72 | + */ | |
| 73 | + public AtomicInteger(int initialValue) { | |
| 74 | + value = initialValue; | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Creates a new AtomicInteger with initial value {@code 0}. | |
| 79 | + */ | |
| 80 | + public AtomicInteger() { | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Gets the current value. | |
| 85 | + * | |
| 86 | + * @return the current value | |
| 87 | + */ | |
| 88 | + public final int get() { | |
| 89 | + return value; | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * Sets to the given value. | |
| 94 | + * | |
| 95 | + * @param newValue the new value | |
| 96 | + */ | |
| 97 | + public final void set(int newValue) { | |
| 98 | + value = newValue; | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * Eventually sets to the given value. | |
| 103 | + * | |
| 104 | + * @param newValue the new value | |
| 105 | + * @since 1.6 | |
| 106 | + */ | |
| 107 | + public final void lazySet(int newValue) { | |
| 108 | + unsafe.putOrderedInt(this, valueOffset, newValue); | |
| 109 | + } | |
| 110 | + | |
| 111 | + /** | |
| 112 | + * Atomically sets to the given value and returns the old value. | |
| 113 | + * | |
| 114 | + * @param newValue the new value | |
| 115 | + * @return the previous value | |
| 116 | + */ | |
| 117 | + public final int getAndSet(int newValue) { | |
| 118 | + for (;;) { | |
| 119 | + int current = get(); | |
| 120 | + if (compareAndSet(current, newValue)) | |
| 121 | + return current; | |
| 122 | + } | |
| 123 | + } | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Atomically sets the value to the given updated value | |
| 127 | + * if the current value {@code ==} the expected value. | |
| 128 | + * | |
| 129 | + * @param expect the expected value | |
| 130 | + * @param update the new value | |
| 131 | + * @return true if successful. False return indicates that | |
| 132 | + * the actual value was not equal to the expected value. | |
| 133 | + */ | |
| 134 | + public final boolean compareAndSet(int expect, int update) { | |
| 135 | + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); | |
| 136 | + } | |
| 137 | + | |
| 138 | + /** | |
| 139 | + * Atomically sets the value to the given updated value | |
| 140 | + * if the current value {@code ==} the expected value. | |
| 141 | + * | |
| 142 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 143 | + * and does not provide ordering guarantees, so is only rarely an | |
| 144 | + * appropriate alternative to {@code compareAndSet}. | |
| 145 | + * | |
| 146 | + * @param expect the expected value | |
| 147 | + * @param update the new value | |
| 148 | + * @return true if successful. | |
| 149 | + */ | |
| 150 | + public final boolean weakCompareAndSet(int expect, int update) { | |
| 151 | + return unsafe.compareAndSwapInt(this, valueOffset, expect, update); | |
| 152 | + } | |
| 153 | + | |
| 154 | + /** | |
| 155 | + * Atomically increments by one the current value. | |
| 156 | + * | |
| 157 | + * @return the previous value | |
| 158 | + */ | |
| 159 | + public final int getAndIncrement() { | |
| 160 | + for (;;) { | |
| 161 | + int current = get(); | |
| 162 | + int next = current + 1; | |
| 163 | + if (compareAndSet(current, next)) | |
| 164 | + return current; | |
| 165 | + } | |
| 166 | + } | |
| 167 | + | |
| 168 | + /** | |
| 169 | + * Atomically decrements by one the current value. | |
| 170 | + * | |
| 171 | + * @return the previous value | |
| 172 | + */ | |
| 173 | + public final int getAndDecrement() { | |
| 174 | + for (;;) { | |
| 175 | + int current = get(); | |
| 176 | + int next = current - 1; | |
| 177 | + if (compareAndSet(current, next)) | |
| 178 | + return current; | |
| 179 | + } | |
| 180 | + } | |
| 181 | + | |
| 182 | + /** | |
| 183 | + * Atomically adds the given value to the current value. | |
| 184 | + * | |
| 185 | + * @param delta the value to add | |
| 186 | + * @return the previous value | |
| 187 | + */ | |
| 188 | + public final int getAndAdd(int delta) { | |
| 189 | + for (;;) { | |
| 190 | + int current = get(); | |
| 191 | + int next = current + delta; | |
| 192 | + if (compareAndSet(current, next)) | |
| 193 | + return current; | |
| 194 | + } | |
| 195 | + } | |
| 196 | + | |
| 197 | + /** | |
| 198 | + * Atomically increments by one the current value. | |
| 199 | + * | |
| 200 | + * @return the updated value | |
| 201 | + */ | |
| 202 | + public final int incrementAndGet() { | |
| 203 | + for (;;) { | |
| 204 | + int current = get(); | |
| 205 | + int next = current + 1; | |
| 206 | + if (compareAndSet(current, next)) | |
| 207 | + return next; | |
| 208 | + } | |
| 209 | + } | |
| 210 | + | |
| 211 | + /** | |
| 212 | + * Atomically decrements by one the current value. | |
| 213 | + * | |
| 214 | + * @return the updated value | |
| 215 | + */ | |
| 216 | + public final int decrementAndGet() { | |
| 217 | + for (;;) { | |
| 218 | + int current = get(); | |
| 219 | + int next = current - 1; | |
| 220 | + if (compareAndSet(current, next)) | |
| 221 | + return next; | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + /** | |
| 226 | + * Atomically adds the given value to the current value. | |
| 227 | + * | |
| 228 | + * @param delta the value to add | |
| 229 | + * @return the updated value | |
| 230 | + */ | |
| 231 | + public final int addAndGet(int delta) { | |
| 232 | + for (;;) { | |
| 233 | + int current = get(); | |
| 234 | + int next = current + delta; | |
| 235 | + if (compareAndSet(current, next)) | |
| 236 | + return next; | |
| 237 | + } | |
| 238 | + } | |
| 239 | + | |
| 240 | + /** | |
| 241 | + * Returns the String representation of the current value. | |
| 242 | + * @return the String representation of the current value. | |
| 243 | + */ | |
| 244 | + public String toString() { | |
| 245 | + return Integer.toString(get()); | |
| 246 | + } | |
| 247 | + | |
| 248 | + | |
| 249 | + public int intValue() { | |
| 250 | + return get(); | |
| 251 | + } | |
| 252 | + | |
| 253 | + public long longValue() { | |
| 254 | + return (long)get(); | |
| 255 | + } | |
| 256 | + | |
| 257 | + public float floatValue() { | |
| 258 | + return (float)get(); | |
| 259 | + } | |
| 260 | + | |
| 261 | + public double doubleValue() { | |
| 262 | + return (double)get(); | |
| 263 | + } | |
| 264 | + | |
| 265 | +} | |
Binary file not shown.
| @@ -0,0 +1,284 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.util.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * An {@code int} array in which elements may be updated atomically. | |
| 42 | + * See the {@link java.util.concurrent.atomic} package | |
| 43 | + * specification for description of the properties of atomic | |
| 44 | + * variables. | |
| 45 | + * @since 1.5 | |
| 46 | + * @author Doug Lea | |
| 47 | + */ | |
| 48 | +public class AtomicIntegerArray implements java.io.Serializable { | |
| 49 | + private static final long serialVersionUID = 2862133569453604235L; | |
| 50 | + | |
| 51 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 52 | + private static final int base = unsafe.arrayBaseOffset(int[].class); | |
| 53 | + private static final int shift; | |
| 54 | + private final int[] array; | |
| 55 | + | |
| 56 | + static { | |
| 57 | + int scale = unsafe.arrayIndexScale(int[].class); | |
| 58 | + if ((scale & (scale - 1)) != 0) | |
| 59 | + throw new Error("data type scale not a power of two"); | |
| 60 | + shift = 31 - Integer.numberOfLeadingZeros(scale); | |
| 61 | + } | |
| 62 | + | |
| 63 | + private long checkedByteOffset(int i) { | |
| 64 | + if (i < 0 || i >= array.length) | |
| 65 | + throw new IndexOutOfBoundsException("index " + i); | |
| 66 | + | |
| 67 | + return byteOffset(i); | |
| 68 | + } | |
| 69 | + | |
| 70 | + private static long byteOffset(int i) { | |
| 71 | + return ((long) i << shift) + base; | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * Creates a new AtomicIntegerArray of the given length, with all | |
| 76 | + * elements initially zero. | |
| 77 | + * | |
| 78 | + * @param length the length of the array | |
| 79 | + */ | |
| 80 | + public AtomicIntegerArray(int length) { | |
| 81 | + array = new int[length]; | |
| 82 | + } | |
| 83 | + | |
| 84 | + /** | |
| 85 | + * Creates a new AtomicIntegerArray with the same length as, and | |
| 86 | + * all elements copied from, the given array. | |
| 87 | + * | |
| 88 | + * @param array the array to copy elements from | |
| 89 | + * @throws NullPointerException if array is null | |
| 90 | + */ | |
| 91 | + public AtomicIntegerArray(int[] array) { | |
| 92 | + // Visibility guaranteed by final field guarantees | |
| 93 | + this.array = array.clone(); | |
| 94 | + } | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * Returns the length of the array. | |
| 98 | + * | |
| 99 | + * @return the length of the array | |
| 100 | + */ | |
| 101 | + public final int length() { | |
| 102 | + return array.length; | |
| 103 | + } | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * Gets the current value at position {@code i}. | |
| 107 | + * | |
| 108 | + * @param i the index | |
| 109 | + * @return the current value | |
| 110 | + */ | |
| 111 | + public final int get(int i) { | |
| 112 | + return getRaw(checkedByteOffset(i)); | |
| 113 | + } | |
| 114 | + | |
| 115 | + private int getRaw(long offset) { | |
| 116 | + return unsafe.getIntVolatile(array, offset); | |
| 117 | + } | |
| 118 | + | |
| 119 | + /** | |
| 120 | + * Sets the element at position {@code i} to the given value. | |
| 121 | + * | |
| 122 | + * @param i the index | |
| 123 | + * @param newValue the new value | |
| 124 | + */ | |
| 125 | + public final void set(int i, int newValue) { | |
| 126 | + unsafe.putIntVolatile(array, checkedByteOffset(i), newValue); | |
| 127 | + } | |
| 128 | + | |
| 129 | + /** | |
| 130 | + * Eventually sets the element at position {@code i} to the given value. | |
| 131 | + * | |
| 132 | + * @param i the index | |
| 133 | + * @param newValue the new value | |
| 134 | + * @since 1.6 | |
| 135 | + */ | |
| 136 | + public final void lazySet(int i, int newValue) { | |
| 137 | + unsafe.putOrderedInt(array, checkedByteOffset(i), newValue); | |
| 138 | + } | |
| 139 | + | |
| 140 | + /** | |
| 141 | + * Atomically sets the element at position {@code i} to the given | |
| 142 | + * value and returns the old value. | |
| 143 | + * | |
| 144 | + * @param i the index | |
| 145 | + * @param newValue the new value | |
| 146 | + * @return the previous value | |
| 147 | + */ | |
| 148 | + public final int getAndSet(int i, int newValue) { | |
| 149 | + long offset = checkedByteOffset(i); | |
| 150 | + while (true) { | |
| 151 | + int current = getRaw(offset); | |
| 152 | + if (compareAndSetRaw(offset, current, newValue)) | |
| 153 | + return current; | |
| 154 | + } | |
| 155 | + } | |
| 156 | + | |
| 157 | + /** | |
| 158 | + * Atomically sets the element at position {@code i} to the given | |
| 159 | + * updated value if the current value {@code ==} the expected value. | |
| 160 | + * | |
| 161 | + * @param i the index | |
| 162 | + * @param expect the expected value | |
| 163 | + * @param update the new value | |
| 164 | + * @return true if successful. False return indicates that | |
| 165 | + * the actual value was not equal to the expected value. | |
| 166 | + */ | |
| 167 | + public final boolean compareAndSet(int i, int expect, int update) { | |
| 168 | + return compareAndSetRaw(checkedByteOffset(i), expect, update); | |
| 169 | + } | |
| 170 | + | |
| 171 | + private boolean compareAndSetRaw(long offset, int expect, int update) { | |
| 172 | + return unsafe.compareAndSwapInt(array, offset, expect, update); | |
| 173 | + } | |
| 174 | + | |
| 175 | + /** | |
| 176 | + * Atomically sets the element at position {@code i} to the given | |
| 177 | + * updated value if the current value {@code ==} the expected value. | |
| 178 | + * | |
| 179 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 180 | + * and does not provide ordering guarantees, so is only rarely an | |
| 181 | + * appropriate alternative to {@code compareAndSet}. | |
| 182 | + * | |
| 183 | + * @param i the index | |
| 184 | + * @param expect the expected value | |
| 185 | + * @param update the new value | |
| 186 | + * @return true if successful. | |
| 187 | + */ | |
| 188 | + public final boolean weakCompareAndSet(int i, int expect, int update) { | |
| 189 | + return compareAndSet(i, expect, update); | |
| 190 | + } | |
| 191 | + | |
| 192 | + /** | |
| 193 | + * Atomically increments by one the element at index {@code i}. | |
| 194 | + * | |
| 195 | + * @param i the index | |
| 196 | + * @return the previous value | |
| 197 | + */ | |
| 198 | + public final int getAndIncrement(int i) { | |
| 199 | + return getAndAdd(i, 1); | |
| 200 | + } | |
| 201 | + | |
| 202 | + /** | |
| 203 | + * Atomically decrements by one the element at index {@code i}. | |
| 204 | + * | |
| 205 | + * @param i the index | |
| 206 | + * @return the previous value | |
| 207 | + */ | |
| 208 | + public final int getAndDecrement(int i) { | |
| 209 | + return getAndAdd(i, -1); | |
| 210 | + } | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * Atomically adds the given value to the element at index {@code i}. | |
| 214 | + * | |
| 215 | + * @param i the index | |
| 216 | + * @param delta the value to add | |
| 217 | + * @return the previous value | |
| 218 | + */ | |
| 219 | + public final int getAndAdd(int i, int delta) { | |
| 220 | + long offset = checkedByteOffset(i); | |
| 221 | + while (true) { | |
| 222 | + int current = getRaw(offset); | |
| 223 | + if (compareAndSetRaw(offset, current, current + delta)) | |
| 224 | + return current; | |
| 225 | + } | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * Atomically increments by one the element at index {@code i}. | |
| 230 | + * | |
| 231 | + * @param i the index | |
| 232 | + * @return the updated value | |
| 233 | + */ | |
| 234 | + public final int incrementAndGet(int i) { | |
| 235 | + return addAndGet(i, 1); | |
| 236 | + } | |
| 237 | + | |
| 238 | + /** | |
| 239 | + * Atomically decrements by one the element at index {@code i}. | |
| 240 | + * | |
| 241 | + * @param i the index | |
| 242 | + * @return the updated value | |
| 243 | + */ | |
| 244 | + public final int decrementAndGet(int i) { | |
| 245 | + return addAndGet(i, -1); | |
| 246 | + } | |
| 247 | + | |
| 248 | + /** | |
| 249 | + * Atomically adds the given value to the element at index {@code i}. | |
| 250 | + * | |
| 251 | + * @param i the index | |
| 252 | + * @param delta the value to add | |
| 253 | + * @return the updated value | |
| 254 | + */ | |
| 255 | + public final int addAndGet(int i, int delta) { | |
| 256 | + long offset = checkedByteOffset(i); | |
| 257 | + while (true) { | |
| 258 | + int current = getRaw(offset); | |
| 259 | + int next = current + delta; | |
| 260 | + if (compareAndSetRaw(offset, current, next)) | |
| 261 | + return next; | |
| 262 | + } | |
| 263 | + } | |
| 264 | + | |
| 265 | + /** | |
| 266 | + * Returns the String representation of the current values of array. | |
| 267 | + * @return the String representation of the current values of array | |
| 268 | + */ | |
| 269 | + public String toString() { | |
| 270 | + int iMax = array.length - 1; | |
| 271 | + if (iMax == -1) | |
| 272 | + return "[]"; | |
| 273 | + | |
| 274 | + StringBuilder b = new StringBuilder(); | |
| 275 | + b.append('['); | |
| 276 | + for (int i = 0; ; i++) { | |
| 277 | + b.append(getRaw(byteOffset(i))); | |
| 278 | + if (i == iMax) | |
| 279 | + return b.append(']').toString(); | |
| 280 | + b.append(',').append(' '); | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,346 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.lang.reflect.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * A reflection-based utility that enables atomic updates to | |
| 42 | + * designated {@code volatile int} fields of designated classes. | |
| 43 | + * This class is designed for use in atomic data structures in which | |
| 44 | + * several fields of the same node are independently subject to atomic | |
| 45 | + * updates. | |
| 46 | + * | |
| 47 | + * <p>Note that the guarantees of the {@code compareAndSet} | |
| 48 | + * method in this class are weaker than in other atomic classes. | |
| 49 | + * Because this class cannot ensure that all uses of the field | |
| 50 | + * are appropriate for purposes of atomic access, it can | |
| 51 | + * guarantee atomicity only with respect to other invocations of | |
| 52 | + * {@code compareAndSet} and {@code set} on the same updater. | |
| 53 | + * | |
| 54 | + * @since 1.5 | |
| 55 | + * @author Doug Lea | |
| 56 | + * @param <T> The type of the object holding the updatable field | |
| 57 | + */ | |
| 58 | +public abstract class AtomicIntegerFieldUpdater<T> { | |
| 59 | + /** | |
| 60 | + * Creates and returns an updater for objects with the given field. | |
| 61 | + * The Class argument is needed to check that reflective types and | |
| 62 | + * generic types match. | |
| 63 | + * | |
| 64 | + * @param tclass the class of the objects holding the field | |
| 65 | + * @param fieldName the name of the field to be updated | |
| 66 | + * @return the updater | |
| 67 | + * @throws IllegalArgumentException if the field is not a | |
| 68 | + * volatile integer type | |
| 69 | + * @throws RuntimeException with a nested reflection-based | |
| 70 | + * exception if the class does not hold field or is the wrong type | |
| 71 | + */ | |
| 72 | + public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { | |
| 73 | + return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Protected do-nothing constructor for use by subclasses. | |
| 78 | + */ | |
| 79 | + protected AtomicIntegerFieldUpdater() { | |
| 80 | + } | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Atomically sets the field of the given object managed by this updater | |
| 84 | + * to the given updated value if the current value {@code ==} the | |
| 85 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 86 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 87 | + * necessarily with respect to other changes in the field. | |
| 88 | + * | |
| 89 | + * @param obj An object whose field to conditionally set | |
| 90 | + * @param expect the expected value | |
| 91 | + * @param update the new value | |
| 92 | + * @return true if successful | |
| 93 | + * @throws ClassCastException if {@code obj} is not an instance | |
| 94 | + * of the class possessing the field established in the constructor | |
| 95 | + */ | |
| 96 | + public abstract boolean compareAndSet(T obj, int expect, int update); | |
| 97 | + | |
| 98 | + /** | |
| 99 | + * Atomically sets the field of the given object managed by this updater | |
| 100 | + * to the given updated value if the current value {@code ==} the | |
| 101 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 102 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 103 | + * necessarily with respect to other changes in the field. | |
| 104 | + * | |
| 105 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 106 | + * and does not provide ordering guarantees, so is only rarely an | |
| 107 | + * appropriate alternative to {@code compareAndSet}. | |
| 108 | + * | |
| 109 | + * @param obj An object whose field to conditionally set | |
| 110 | + * @param expect the expected value | |
| 111 | + * @param update the new value | |
| 112 | + * @return true if successful | |
| 113 | + * @throws ClassCastException if {@code obj} is not an instance | |
| 114 | + * of the class possessing the field established in the constructor | |
| 115 | + */ | |
| 116 | + public abstract boolean weakCompareAndSet(T obj, int expect, int update); | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Sets the field of the given object managed by this updater to the | |
| 120 | + * given updated value. This operation is guaranteed to act as a volatile | |
| 121 | + * store with respect to subsequent invocations of {@code compareAndSet}. | |
| 122 | + * | |
| 123 | + * @param obj An object whose field to set | |
| 124 | + * @param newValue the new value | |
| 125 | + */ | |
| 126 | + public abstract void set(T obj, int newValue); | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * Eventually sets the field of the given object managed by this | |
| 130 | + * updater to the given updated value. | |
| 131 | + * | |
| 132 | + * @param obj An object whose field to set | |
| 133 | + * @param newValue the new value | |
| 134 | + * @since 1.6 | |
| 135 | + */ | |
| 136 | + public abstract void lazySet(T obj, int newValue); | |
| 137 | + | |
| 138 | + | |
| 139 | + /** | |
| 140 | + * Gets the current value held in the field of the given object managed | |
| 141 | + * by this updater. | |
| 142 | + * | |
| 143 | + * @param obj An object whose field to get | |
| 144 | + * @return the current value | |
| 145 | + */ | |
| 146 | + public abstract int get(T obj); | |
| 147 | + | |
| 148 | + /** | |
| 149 | + * Atomically sets the field of the given object managed by this updater | |
| 150 | + * to the given value and returns the old value. | |
| 151 | + * | |
| 152 | + * @param obj An object whose field to get and set | |
| 153 | + * @param newValue the new value | |
| 154 | + * @return the previous value | |
| 155 | + */ | |
| 156 | + public int getAndSet(T obj, int newValue) { | |
| 157 | + for (;;) { | |
| 158 | + int current = get(obj); | |
| 159 | + if (compareAndSet(obj, current, newValue)) | |
| 160 | + return current; | |
| 161 | + } | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * Atomically increments by one the current value of the field of the | |
| 166 | + * given object managed by this updater. | |
| 167 | + * | |
| 168 | + * @param obj An object whose field to get and set | |
| 169 | + * @return the previous value | |
| 170 | + */ | |
| 171 | + public int getAndIncrement(T obj) { | |
| 172 | + for (;;) { | |
| 173 | + int current = get(obj); | |
| 174 | + int next = current + 1; | |
| 175 | + if (compareAndSet(obj, current, next)) | |
| 176 | + return current; | |
| 177 | + } | |
| 178 | + } | |
| 179 | + | |
| 180 | + /** | |
| 181 | + * Atomically decrements by one the current value of the field of the | |
| 182 | + * given object managed by this updater. | |
| 183 | + * | |
| 184 | + * @param obj An object whose field to get and set | |
| 185 | + * @return the previous value | |
| 186 | + */ | |
| 187 | + public int getAndDecrement(T obj) { | |
| 188 | + for (;;) { | |
| 189 | + int current = get(obj); | |
| 190 | + int next = current - 1; | |
| 191 | + if (compareAndSet(obj, current, next)) | |
| 192 | + return current; | |
| 193 | + } | |
| 194 | + } | |
| 195 | + | |
| 196 | + /** | |
| 197 | + * Atomically adds the given value to the current value of the field of | |
| 198 | + * the given object managed by this updater. | |
| 199 | + * | |
| 200 | + * @param obj An object whose field to get and set | |
| 201 | + * @param delta the value to add | |
| 202 | + * @return the previous value | |
| 203 | + */ | |
| 204 | + public int getAndAdd(T obj, int delta) { | |
| 205 | + for (;;) { | |
| 206 | + int current = get(obj); | |
| 207 | + int next = current + delta; | |
| 208 | + if (compareAndSet(obj, current, next)) | |
| 209 | + return current; | |
| 210 | + } | |
| 211 | + } | |
| 212 | + | |
| 213 | + /** | |
| 214 | + * Atomically increments by one the current value of the field of the | |
| 215 | + * given object managed by this updater. | |
| 216 | + * | |
| 217 | + * @param obj An object whose field to get and set | |
| 218 | + * @return the updated value | |
| 219 | + */ | |
| 220 | + public int incrementAndGet(T obj) { | |
| 221 | + for (;;) { | |
| 222 | + int current = get(obj); | |
| 223 | + int next = current + 1; | |
| 224 | + if (compareAndSet(obj, current, next)) | |
| 225 | + return next; | |
| 226 | + } | |
| 227 | + } | |
| 228 | + | |
| 229 | + /** | |
| 230 | + * Atomically decrements by one the current value of the field of the | |
| 231 | + * given object managed by this updater. | |
| 232 | + * | |
| 233 | + * @param obj An object whose field to get and set | |
| 234 | + * @return the updated value | |
| 235 | + */ | |
| 236 | + public int decrementAndGet(T obj) { | |
| 237 | + for (;;) { | |
| 238 | + int current = get(obj); | |
| 239 | + int next = current - 1; | |
| 240 | + if (compareAndSet(obj, current, next)) | |
| 241 | + return next; | |
| 242 | + } | |
| 243 | + } | |
| 244 | + | |
| 245 | + /** | |
| 246 | + * Atomically adds the given value to the current value of the field of | |
| 247 | + * the given object managed by this updater. | |
| 248 | + * | |
| 249 | + * @param obj An object whose field to get and set | |
| 250 | + * @param delta the value to add | |
| 251 | + * @return the updated value | |
| 252 | + */ | |
| 253 | + public int addAndGet(T obj, int delta) { | |
| 254 | + for (;;) { | |
| 255 | + int current = get(obj); | |
| 256 | + int next = current + delta; | |
| 257 | + if (compareAndSet(obj, current, next)) | |
| 258 | + return next; | |
| 259 | + } | |
| 260 | + } | |
| 261 | + | |
| 262 | + /** | |
| 263 | + * Standard hotspot implementation using intrinsics | |
| 264 | + */ | |
| 265 | + private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> { | |
| 266 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 267 | + private final long offset; | |
| 268 | + private final Class<T> tclass; | |
| 269 | + private final Class cclass; | |
| 270 | + | |
| 271 | + AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) { | |
| 272 | + Field field = null; | |
| 273 | + Class caller = null; | |
| 274 | + int modifiers = 0; | |
| 275 | + try { | |
| 276 | + field = tclass.getDeclaredField(fieldName); | |
| 277 | + caller = sun.reflect.Reflection.getCallerClass(3); | |
| 278 | + modifiers = field.getModifiers(); | |
| 279 | + sun.reflect.misc.ReflectUtil.ensureMemberAccess( | |
| 280 | + caller, tclass, null, modifiers); | |
| 281 | + sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); | |
| 282 | + } catch (Exception ex) { | |
| 283 | + throw new RuntimeException(ex); | |
| 284 | + } | |
| 285 | + | |
| 286 | + Class fieldt = field.getType(); | |
| 287 | + if (fieldt != int.class) | |
| 288 | + throw new IllegalArgumentException("Must be integer type"); | |
| 289 | + | |
| 290 | + if (!Modifier.isVolatile(modifiers)) | |
| 291 | + throw new IllegalArgumentException("Must be volatile type"); | |
| 292 | + | |
| 293 | + this.cclass = (Modifier.isProtected(modifiers) && | |
| 294 | + caller != tclass) ? caller : null; | |
| 295 | + this.tclass = tclass; | |
| 296 | + offset = unsafe.objectFieldOffset(field); | |
| 297 | + } | |
| 298 | + | |
| 299 | + private void fullCheck(T obj) { | |
| 300 | + if (!tclass.isInstance(obj)) | |
| 301 | + throw new ClassCastException(); | |
| 302 | + if (cclass != null) | |
| 303 | + ensureProtectedAccess(obj); | |
| 304 | + } | |
| 305 | + | |
| 306 | + public boolean compareAndSet(T obj, int expect, int update) { | |
| 307 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 308 | + return unsafe.compareAndSwapInt(obj, offset, expect, update); | |
| 309 | + } | |
| 310 | + | |
| 311 | + public boolean weakCompareAndSet(T obj, int expect, int update) { | |
| 312 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 313 | + return unsafe.compareAndSwapInt(obj, offset, expect, update); | |
| 314 | + } | |
| 315 | + | |
| 316 | + public void set(T obj, int newValue) { | |
| 317 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 318 | + unsafe.putIntVolatile(obj, offset, newValue); | |
| 319 | + } | |
| 320 | + | |
| 321 | + public void lazySet(T obj, int newValue) { | |
| 322 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 323 | + unsafe.putOrderedInt(obj, offset, newValue); | |
| 324 | + } | |
| 325 | + | |
| 326 | + public final int get(T obj) { | |
| 327 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 328 | + return unsafe.getIntVolatile(obj, offset); | |
| 329 | + } | |
| 330 | + | |
| 331 | + private void ensureProtectedAccess(T obj) { | |
| 332 | + if (cclass.isInstance(obj)) { | |
| 333 | + return; | |
| 334 | + } | |
| 335 | + throw new RuntimeException( | |
| 336 | + new IllegalAccessException("Class " + | |
| 337 | + cclass.getName() + | |
| 338 | + " can not access a protected member of class " + | |
| 339 | + tclass.getName() + | |
| 340 | + " using an instance of " + | |
| 341 | + obj.getClass().getName() | |
| 342 | + ) | |
| 343 | + ); | |
| 344 | + } | |
| 345 | + } | |
| 346 | +} | |
Binary file not shown.
| @@ -0,0 +1,279 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * A {@code long} value that may be updated atomically. See the | |
| 41 | + * {@link java.util.concurrent.atomic} package specification for | |
| 42 | + * description of the properties of atomic variables. An | |
| 43 | + * {@code AtomicLong} is used in applications such as atomically | |
| 44 | + * incremented sequence numbers, and cannot be used as a replacement | |
| 45 | + * for a {@link java.lang.Long}. However, this class does extend | |
| 46 | + * {@code Number} to allow uniform access by tools and utilities that | |
| 47 | + * deal with numerically-based classes. | |
| 48 | + * | |
| 49 | + * @since 1.5 | |
| 50 | + * @author Doug Lea | |
| 51 | + */ | |
| 52 | +public class AtomicLong extends Number implements java.io.Serializable { | |
| 53 | + private static final long serialVersionUID = 1927816293512124184L; | |
| 54 | + | |
| 55 | + // setup to use Unsafe.compareAndSwapLong for updates | |
| 56 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 57 | + private static final long valueOffset; | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Records whether the underlying JVM supports lockless | |
| 61 | + * compareAndSwap for longs. While the Unsafe.compareAndSwapLong | |
| 62 | + * method works in either case, some constructions should be | |
| 63 | + * handled at Java level to avoid locking user-visible locks. | |
| 64 | + */ | |
| 65 | + static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * Returns whether underlying JVM supports lockless CompareAndSet | |
| 69 | + * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS. | |
| 70 | + */ | |
| 71 | + private static native boolean VMSupportsCS8(); | |
| 72 | + | |
| 73 | + static { | |
| 74 | + try { | |
| 75 | + valueOffset = unsafe.objectFieldOffset | |
| 76 | + (AtomicLong.class.getDeclaredField("value")); | |
| 77 | + } catch (Exception ex) { throw new Error(ex); } | |
| 78 | + } | |
| 79 | + | |
| 80 | + private volatile long value; | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * Creates a new AtomicLong with the given initial value. | |
| 84 | + * | |
| 85 | + * @param initialValue the initial value | |
| 86 | + */ | |
| 87 | + public AtomicLong(long initialValue) { | |
| 88 | + value = initialValue; | |
| 89 | + } | |
| 90 | + | |
| 91 | + /** | |
| 92 | + * Creates a new AtomicLong with initial value {@code 0}. | |
| 93 | + */ | |
| 94 | + public AtomicLong() { | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Gets the current value. | |
| 99 | + * | |
| 100 | + * @return the current value | |
| 101 | + */ | |
| 102 | + public final long get() { | |
| 103 | + return value; | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * Sets to the given value. | |
| 108 | + * | |
| 109 | + * @param newValue the new value | |
| 110 | + */ | |
| 111 | + public final void set(long newValue) { | |
| 112 | + value = newValue; | |
| 113 | + } | |
| 114 | + | |
| 115 | + /** | |
| 116 | + * Eventually sets to the given value. | |
| 117 | + * | |
| 118 | + * @param newValue the new value | |
| 119 | + * @since 1.6 | |
| 120 | + */ | |
| 121 | + public final void lazySet(long newValue) { | |
| 122 | + unsafe.putOrderedLong(this, valueOffset, newValue); | |
| 123 | + } | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * Atomically sets to the given value and returns the old value. | |
| 127 | + * | |
| 128 | + * @param newValue the new value | |
| 129 | + * @return the previous value | |
| 130 | + */ | |
| 131 | + public final long getAndSet(long newValue) { | |
| 132 | + while (true) { | |
| 133 | + long current = get(); | |
| 134 | + if (compareAndSet(current, newValue)) | |
| 135 | + return current; | |
| 136 | + } | |
| 137 | + } | |
| 138 | + | |
| 139 | + /** | |
| 140 | + * Atomically sets the value to the given updated value | |
| 141 | + * if the current value {@code ==} the expected value. | |
| 142 | + * | |
| 143 | + * @param expect the expected value | |
| 144 | + * @param update the new value | |
| 145 | + * @return true if successful. False return indicates that | |
| 146 | + * the actual value was not equal to the expected value. | |
| 147 | + */ | |
| 148 | + public final boolean compareAndSet(long expect, long update) { | |
| 149 | + return unsafe.compareAndSwapLong(this, valueOffset, expect, update); | |
| 150 | + } | |
| 151 | + | |
| 152 | + /** | |
| 153 | + * Atomically sets the value to the given updated value | |
| 154 | + * if the current value {@code ==} the expected value. | |
| 155 | + * | |
| 156 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 157 | + * and does not provide ordering guarantees, so is only rarely an | |
| 158 | + * appropriate alternative to {@code compareAndSet}. | |
| 159 | + * | |
| 160 | + * @param expect the expected value | |
| 161 | + * @param update the new value | |
| 162 | + * @return true if successful. | |
| 163 | + */ | |
| 164 | + public final boolean weakCompareAndSet(long expect, long update) { | |
| 165 | + return unsafe.compareAndSwapLong(this, valueOffset, expect, update); | |
| 166 | + } | |
| 167 | + | |
| 168 | + /** | |
| 169 | + * Atomically increments by one the current value. | |
| 170 | + * | |
| 171 | + * @return the previous value | |
| 172 | + */ | |
| 173 | + public final long getAndIncrement() { | |
| 174 | + while (true) { | |
| 175 | + long current = get(); | |
| 176 | + long next = current + 1; | |
| 177 | + if (compareAndSet(current, next)) | |
| 178 | + return current; | |
| 179 | + } | |
| 180 | + } | |
| 181 | + | |
| 182 | + /** | |
| 183 | + * Atomically decrements by one the current value. | |
| 184 | + * | |
| 185 | + * @return the previous value | |
| 186 | + */ | |
| 187 | + public final long getAndDecrement() { | |
| 188 | + while (true) { | |
| 189 | + long current = get(); | |
| 190 | + long next = current - 1; | |
| 191 | + if (compareAndSet(current, next)) | |
| 192 | + return current; | |
| 193 | + } | |
| 194 | + } | |
| 195 | + | |
| 196 | + /** | |
| 197 | + * Atomically adds the given value to the current value. | |
| 198 | + * | |
| 199 | + * @param delta the value to add | |
| 200 | + * @return the previous value | |
| 201 | + */ | |
| 202 | + public final long getAndAdd(long delta) { | |
| 203 | + while (true) { | |
| 204 | + long current = get(); | |
| 205 | + long next = current + delta; | |
| 206 | + if (compareAndSet(current, next)) | |
| 207 | + return current; | |
| 208 | + } | |
| 209 | + } | |
| 210 | + | |
| 211 | + /** | |
| 212 | + * Atomically increments by one the current value. | |
| 213 | + * | |
| 214 | + * @return the updated value | |
| 215 | + */ | |
| 216 | + public final long incrementAndGet() { | |
| 217 | + for (;;) { | |
| 218 | + long current = get(); | |
| 219 | + long next = current + 1; | |
| 220 | + if (compareAndSet(current, next)) | |
| 221 | + return next; | |
| 222 | + } | |
| 223 | + } | |
| 224 | + | |
| 225 | + /** | |
| 226 | + * Atomically decrements by one the current value. | |
| 227 | + * | |
| 228 | + * @return the updated value | |
| 229 | + */ | |
| 230 | + public final long decrementAndGet() { | |
| 231 | + for (;;) { | |
| 232 | + long current = get(); | |
| 233 | + long next = current - 1; | |
| 234 | + if (compareAndSet(current, next)) | |
| 235 | + return next; | |
| 236 | + } | |
| 237 | + } | |
| 238 | + | |
| 239 | + /** | |
| 240 | + * Atomically adds the given value to the current value. | |
| 241 | + * | |
| 242 | + * @param delta the value to add | |
| 243 | + * @return the updated value | |
| 244 | + */ | |
| 245 | + public final long addAndGet(long delta) { | |
| 246 | + for (;;) { | |
| 247 | + long current = get(); | |
| 248 | + long next = current + delta; | |
| 249 | + if (compareAndSet(current, next)) | |
| 250 | + return next; | |
| 251 | + } | |
| 252 | + } | |
| 253 | + | |
| 254 | + /** | |
| 255 | + * Returns the String representation of the current value. | |
| 256 | + * @return the String representation of the current value. | |
| 257 | + */ | |
| 258 | + public String toString() { | |
| 259 | + return Long.toString(get()); | |
| 260 | + } | |
| 261 | + | |
| 262 | + | |
| 263 | + public int intValue() { | |
| 264 | + return (int)get(); | |
| 265 | + } | |
| 266 | + | |
| 267 | + public long longValue() { | |
| 268 | + return get(); | |
| 269 | + } | |
| 270 | + | |
| 271 | + public float floatValue() { | |
| 272 | + return (float)get(); | |
| 273 | + } | |
| 274 | + | |
| 275 | + public double doubleValue() { | |
| 276 | + return (double)get(); | |
| 277 | + } | |
| 278 | + | |
| 279 | +} | |
Binary file not shown.
| @@ -0,0 +1,284 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.util.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * A {@code long} array in which elements may be updated atomically. | |
| 42 | + * See the {@link java.util.concurrent.atomic} package specification | |
| 43 | + * for description of the properties of atomic variables. | |
| 44 | + * @since 1.5 | |
| 45 | + * @author Doug Lea | |
| 46 | + */ | |
| 47 | +public class AtomicLongArray implements java.io.Serializable { | |
| 48 | + private static final long serialVersionUID = -2308431214976778248L; | |
| 49 | + | |
| 50 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 51 | + private static final int base = unsafe.arrayBaseOffset(long[].class); | |
| 52 | + private static final int shift; | |
| 53 | + private final long[] array; | |
| 54 | + | |
| 55 | + static { | |
| 56 | + int scale = unsafe.arrayIndexScale(long[].class); | |
| 57 | + if ((scale & (scale - 1)) != 0) | |
| 58 | + throw new Error("data type scale not a power of two"); | |
| 59 | + shift = 31 - Integer.numberOfLeadingZeros(scale); | |
| 60 | + } | |
| 61 | + | |
| 62 | + private long checkedByteOffset(int i) { | |
| 63 | + if (i < 0 || i >= array.length) | |
| 64 | + throw new IndexOutOfBoundsException("index " + i); | |
| 65 | + | |
| 66 | + return byteOffset(i); | |
| 67 | + } | |
| 68 | + | |
| 69 | + private static long byteOffset(int i) { | |
| 70 | + return ((long) i << shift) + base; | |
| 71 | + } | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * Creates a new AtomicLongArray of the given length, with all | |
| 75 | + * elements initially zero. | |
| 76 | + * | |
| 77 | + * @param length the length of the array | |
| 78 | + */ | |
| 79 | + public AtomicLongArray(int length) { | |
| 80 | + array = new long[length]; | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Creates a new AtomicLongArray with the same length as, and | |
| 85 | + * all elements copied from, the given array. | |
| 86 | + * | |
| 87 | + * @param array the array to copy elements from | |
| 88 | + * @throws NullPointerException if array is null | |
| 89 | + */ | |
| 90 | + public AtomicLongArray(long[] array) { | |
| 91 | + // Visibility guaranteed by final field guarantees | |
| 92 | + this.array = array.clone(); | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Returns the length of the array. | |
| 97 | + * | |
| 98 | + * @return the length of the array | |
| 99 | + */ | |
| 100 | + public final int length() { | |
| 101 | + return array.length; | |
| 102 | + } | |
| 103 | + | |
| 104 | + /** | |
| 105 | + * Gets the current value at position {@code i}. | |
| 106 | + * | |
| 107 | + * @param i the index | |
| 108 | + * @return the current value | |
| 109 | + */ | |
| 110 | + public final long get(int i) { | |
| 111 | + return getRaw(checkedByteOffset(i)); | |
| 112 | + } | |
| 113 | + | |
| 114 | + private long getRaw(long offset) { | |
| 115 | + return unsafe.getLongVolatile(array, offset); | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * Sets the element at position {@code i} to the given value. | |
| 120 | + * | |
| 121 | + * @param i the index | |
| 122 | + * @param newValue the new value | |
| 123 | + */ | |
| 124 | + public final void set(int i, long newValue) { | |
| 125 | + unsafe.putLongVolatile(array, checkedByteOffset(i), newValue); | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * Eventually sets the element at position {@code i} to the given value. | |
| 130 | + * | |
| 131 | + * @param i the index | |
| 132 | + * @param newValue the new value | |
| 133 | + * @since 1.6 | |
| 134 | + */ | |
| 135 | + public final void lazySet(int i, long newValue) { | |
| 136 | + unsafe.putOrderedLong(array, checkedByteOffset(i), newValue); | |
| 137 | + } | |
| 138 | + | |
| 139 | + | |
| 140 | + /** | |
| 141 | + * Atomically sets the element at position {@code i} to the given value | |
| 142 | + * and returns the old value. | |
| 143 | + * | |
| 144 | + * @param i the index | |
| 145 | + * @param newValue the new value | |
| 146 | + * @return the previous value | |
| 147 | + */ | |
| 148 | + public final long getAndSet(int i, long newValue) { | |
| 149 | + long offset = checkedByteOffset(i); | |
| 150 | + while (true) { | |
| 151 | + long current = getRaw(offset); | |
| 152 | + if (compareAndSetRaw(offset, current, newValue)) | |
| 153 | + return current; | |
| 154 | + } | |
| 155 | + } | |
| 156 | + | |
| 157 | + /** | |
| 158 | + * Atomically sets the element at position {@code i} to the given | |
| 159 | + * updated value if the current value {@code ==} the expected value. | |
| 160 | + * | |
| 161 | + * @param i the index | |
| 162 | + * @param expect the expected value | |
| 163 | + * @param update the new value | |
| 164 | + * @return true if successful. False return indicates that | |
| 165 | + * the actual value was not equal to the expected value. | |
| 166 | + */ | |
| 167 | + public final boolean compareAndSet(int i, long expect, long update) { | |
| 168 | + return compareAndSetRaw(checkedByteOffset(i), expect, update); | |
| 169 | + } | |
| 170 | + | |
| 171 | + private boolean compareAndSetRaw(long offset, long expect, long update) { | |
| 172 | + return unsafe.compareAndSwapLong(array, offset, expect, update); | |
| 173 | + } | |
| 174 | + | |
| 175 | + /** | |
| 176 | + * Atomically sets the element at position {@code i} to the given | |
| 177 | + * updated value if the current value {@code ==} the expected value. | |
| 178 | + * | |
| 179 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 180 | + * and does not provide ordering guarantees, so is only rarely an | |
| 181 | + * appropriate alternative to {@code compareAndSet}. | |
| 182 | + * | |
| 183 | + * @param i the index | |
| 184 | + * @param expect the expected value | |
| 185 | + * @param update the new value | |
| 186 | + * @return true if successful. | |
| 187 | + */ | |
| 188 | + public final boolean weakCompareAndSet(int i, long expect, long update) { | |
| 189 | + return compareAndSet(i, expect, update); | |
| 190 | + } | |
| 191 | + | |
| 192 | + /** | |
| 193 | + * Atomically increments by one the element at index {@code i}. | |
| 194 | + * | |
| 195 | + * @param i the index | |
| 196 | + * @return the previous value | |
| 197 | + */ | |
| 198 | + public final long getAndIncrement(int i) { | |
| 199 | + return getAndAdd(i, 1); | |
| 200 | + } | |
| 201 | + | |
| 202 | + /** | |
| 203 | + * Atomically decrements by one the element at index {@code i}. | |
| 204 | + * | |
| 205 | + * @param i the index | |
| 206 | + * @return the previous value | |
| 207 | + */ | |
| 208 | + public final long getAndDecrement(int i) { | |
| 209 | + return getAndAdd(i, -1); | |
| 210 | + } | |
| 211 | + | |
| 212 | + /** | |
| 213 | + * Atomically adds the given value to the element at index {@code i}. | |
| 214 | + * | |
| 215 | + * @param i the index | |
| 216 | + * @param delta the value to add | |
| 217 | + * @return the previous value | |
| 218 | + */ | |
| 219 | + public final long getAndAdd(int i, long delta) { | |
| 220 | + long offset = checkedByteOffset(i); | |
| 221 | + while (true) { | |
| 222 | + long current = getRaw(offset); | |
| 223 | + if (compareAndSetRaw(offset, current, current + delta)) | |
| 224 | + return current; | |
| 225 | + } | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * Atomically increments by one the element at index {@code i}. | |
| 230 | + * | |
| 231 | + * @param i the index | |
| 232 | + * @return the updated value | |
| 233 | + */ | |
| 234 | + public final long incrementAndGet(int i) { | |
| 235 | + return addAndGet(i, 1); | |
| 236 | + } | |
| 237 | + | |
| 238 | + /** | |
| 239 | + * Atomically decrements by one the element at index {@code i}. | |
| 240 | + * | |
| 241 | + * @param i the index | |
| 242 | + * @return the updated value | |
| 243 | + */ | |
| 244 | + public final long decrementAndGet(int i) { | |
| 245 | + return addAndGet(i, -1); | |
| 246 | + } | |
| 247 | + | |
| 248 | + /** | |
| 249 | + * Atomically adds the given value to the element at index {@code i}. | |
| 250 | + * | |
| 251 | + * @param i the index | |
| 252 | + * @param delta the value to add | |
| 253 | + * @return the updated value | |
| 254 | + */ | |
| 255 | + public long addAndGet(int i, long delta) { | |
| 256 | + long offset = checkedByteOffset(i); | |
| 257 | + while (true) { | |
| 258 | + long current = getRaw(offset); | |
| 259 | + long next = current + delta; | |
| 260 | + if (compareAndSetRaw(offset, current, next)) | |
| 261 | + return next; | |
| 262 | + } | |
| 263 | + } | |
| 264 | + | |
| 265 | + /** | |
| 266 | + * Returns the String representation of the current values of array. | |
| 267 | + * @return the String representation of the current values of array | |
| 268 | + */ | |
| 269 | + public String toString() { | |
| 270 | + int iMax = array.length - 1; | |
| 271 | + if (iMax == -1) | |
| 272 | + return "[]"; | |
| 273 | + | |
| 274 | + StringBuilder b = new StringBuilder(); | |
| 275 | + b.append('['); | |
| 276 | + for (int i = 0; ; i++) { | |
| 277 | + b.append(getRaw(byteOffset(i))); | |
| 278 | + if (i == iMax) | |
| 279 | + return b.append(']').toString(); | |
| 280 | + b.append(',').append(' '); | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,436 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.lang.reflect.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * A reflection-based utility that enables atomic updates to | |
| 42 | + * designated {@code volatile long} fields of designated classes. | |
| 43 | + * This class is designed for use in atomic data structures in which | |
| 44 | + * several fields of the same node are independently subject to atomic | |
| 45 | + * updates. | |
| 46 | + * | |
| 47 | + * <p>Note that the guarantees of the {@code compareAndSet} | |
| 48 | + * method in this class are weaker than in other atomic classes. | |
| 49 | + * Because this class cannot ensure that all uses of the field | |
| 50 | + * are appropriate for purposes of atomic access, it can | |
| 51 | + * guarantee atomicity only with respect to other invocations of | |
| 52 | + * {@code compareAndSet} and {@code set} on the same updater. | |
| 53 | + * | |
| 54 | + * @since 1.5 | |
| 55 | + * @author Doug Lea | |
| 56 | + * @param <T> The type of the object holding the updatable field | |
| 57 | + */ | |
| 58 | +public abstract class AtomicLongFieldUpdater<T> { | |
| 59 | + /** | |
| 60 | + * Creates and returns an updater for objects with the given field. | |
| 61 | + * The Class argument is needed to check that reflective types and | |
| 62 | + * generic types match. | |
| 63 | + * | |
| 64 | + * @param tclass the class of the objects holding the field | |
| 65 | + * @param fieldName the name of the field to be updated. | |
| 66 | + * @return the updater | |
| 67 | + * @throws IllegalArgumentException if the field is not a | |
| 68 | + * volatile long type. | |
| 69 | + * @throws RuntimeException with a nested reflection-based | |
| 70 | + * exception if the class does not hold field or is the wrong type. | |
| 71 | + */ | |
| 72 | + public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { | |
| 73 | + if (AtomicLong.VM_SUPPORTS_LONG_CAS) | |
| 74 | + return new CASUpdater<U>(tclass, fieldName); | |
| 75 | + else | |
| 76 | + return new LockedUpdater<U>(tclass, fieldName); | |
| 77 | + } | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * Protected do-nothing constructor for use by subclasses. | |
| 81 | + */ | |
| 82 | + protected AtomicLongFieldUpdater() { | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Atomically sets the field of the given object managed by this updater | |
| 87 | + * to the given updated value if the current value {@code ==} the | |
| 88 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 89 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 90 | + * necessarily with respect to other changes in the field. | |
| 91 | + * | |
| 92 | + * @param obj An object whose field to conditionally set | |
| 93 | + * @param expect the expected value | |
| 94 | + * @param update the new value | |
| 95 | + * @return true if successful. | |
| 96 | + * @throws ClassCastException if {@code obj} is not an instance | |
| 97 | + * of the class possessing the field established in the constructor. | |
| 98 | + */ | |
| 99 | + public abstract boolean compareAndSet(T obj, long expect, long update); | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * Atomically sets the field of the given object managed by this updater | |
| 103 | + * to the given updated value if the current value {@code ==} the | |
| 104 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 105 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 106 | + * necessarily with respect to other changes in the field. | |
| 107 | + * | |
| 108 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 109 | + * and does not provide ordering guarantees, so is only rarely an | |
| 110 | + * appropriate alternative to {@code compareAndSet}. | |
| 111 | + * | |
| 112 | + * @param obj An object whose field to conditionally set | |
| 113 | + * @param expect the expected value | |
| 114 | + * @param update the new value | |
| 115 | + * @return true if successful. | |
| 116 | + * @throws ClassCastException if {@code obj} is not an instance | |
| 117 | + * of the class possessing the field established in the constructor. | |
| 118 | + */ | |
| 119 | + public abstract boolean weakCompareAndSet(T obj, long expect, long update); | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * Sets the field of the given object managed by this updater to the | |
| 123 | + * given updated value. This operation is guaranteed to act as a volatile | |
| 124 | + * store with respect to subsequent invocations of {@code compareAndSet}. | |
| 125 | + * | |
| 126 | + * @param obj An object whose field to set | |
| 127 | + * @param newValue the new value | |
| 128 | + */ | |
| 129 | + public abstract void set(T obj, long newValue); | |
| 130 | + | |
| 131 | + /** | |
| 132 | + * Eventually sets the field of the given object managed by this | |
| 133 | + * updater to the given updated value. | |
| 134 | + * | |
| 135 | + * @param obj An object whose field to set | |
| 136 | + * @param newValue the new value | |
| 137 | + * @since 1.6 | |
| 138 | + */ | |
| 139 | + public abstract void lazySet(T obj, long newValue); | |
| 140 | + | |
| 141 | + /** | |
| 142 | + * Gets the current value held in the field of the given object managed | |
| 143 | + * by this updater. | |
| 144 | + * | |
| 145 | + * @param obj An object whose field to get | |
| 146 | + * @return the current value | |
| 147 | + */ | |
| 148 | + public abstract long get(T obj); | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * Atomically sets the field of the given object managed by this updater | |
| 152 | + * to the given value and returns the old value. | |
| 153 | + * | |
| 154 | + * @param obj An object whose field to get and set | |
| 155 | + * @param newValue the new value | |
| 156 | + * @return the previous value | |
| 157 | + */ | |
| 158 | + public long getAndSet(T obj, long newValue) { | |
| 159 | + for (;;) { | |
| 160 | + long current = get(obj); | |
| 161 | + if (compareAndSet(obj, current, newValue)) | |
| 162 | + return current; | |
| 163 | + } | |
| 164 | + } | |
| 165 | + | |
| 166 | + /** | |
| 167 | + * Atomically increments by one the current value of the field of the | |
| 168 | + * given object managed by this updater. | |
| 169 | + * | |
| 170 | + * @param obj An object whose field to get and set | |
| 171 | + * @return the previous value | |
| 172 | + */ | |
| 173 | + public long getAndIncrement(T obj) { | |
| 174 | + for (;;) { | |
| 175 | + long current = get(obj); | |
| 176 | + long next = current + 1; | |
| 177 | + if (compareAndSet(obj, current, next)) | |
| 178 | + return current; | |
| 179 | + } | |
| 180 | + } | |
| 181 | + | |
| 182 | + /** | |
| 183 | + * Atomically decrements by one the current value of the field of the | |
| 184 | + * given object managed by this updater. | |
| 185 | + * | |
| 186 | + * @param obj An object whose field to get and set | |
| 187 | + * @return the previous value | |
| 188 | + */ | |
| 189 | + public long getAndDecrement(T obj) { | |
| 190 | + for (;;) { | |
| 191 | + long current = get(obj); | |
| 192 | + long next = current - 1; | |
| 193 | + if (compareAndSet(obj, current, next)) | |
| 194 | + return current; | |
| 195 | + } | |
| 196 | + } | |
| 197 | + | |
| 198 | + /** | |
| 199 | + * Atomically adds the given value to the current value of the field of | |
| 200 | + * the given object managed by this updater. | |
| 201 | + * | |
| 202 | + * @param obj An object whose field to get and set | |
| 203 | + * @param delta the value to add | |
| 204 | + * @return the previous value | |
| 205 | + */ | |
| 206 | + public long getAndAdd(T obj, long delta) { | |
| 207 | + for (;;) { | |
| 208 | + long current = get(obj); | |
| 209 | + long next = current + delta; | |
| 210 | + if (compareAndSet(obj, current, next)) | |
| 211 | + return current; | |
| 212 | + } | |
| 213 | + } | |
| 214 | + | |
| 215 | + /** | |
| 216 | + * Atomically increments by one the current value of the field of the | |
| 217 | + * given object managed by this updater. | |
| 218 | + * | |
| 219 | + * @param obj An object whose field to get and set | |
| 220 | + * @return the updated value | |
| 221 | + */ | |
| 222 | + public long incrementAndGet(T obj) { | |
| 223 | + for (;;) { | |
| 224 | + long current = get(obj); | |
| 225 | + long next = current + 1; | |
| 226 | + if (compareAndSet(obj, current, next)) | |
| 227 | + return next; | |
| 228 | + } | |
| 229 | + } | |
| 230 | + | |
| 231 | + /** | |
| 232 | + * Atomically decrements by one the current value of the field of the | |
| 233 | + * given object managed by this updater. | |
| 234 | + * | |
| 235 | + * @param obj An object whose field to get and set | |
| 236 | + * @return the updated value | |
| 237 | + */ | |
| 238 | + public long decrementAndGet(T obj) { | |
| 239 | + for (;;) { | |
| 240 | + long current = get(obj); | |
| 241 | + long next = current - 1; | |
| 242 | + if (compareAndSet(obj, current, next)) | |
| 243 | + return next; | |
| 244 | + } | |
| 245 | + } | |
| 246 | + | |
| 247 | + /** | |
| 248 | + * Atomically adds the given value to the current value of the field of | |
| 249 | + * the given object managed by this updater. | |
| 250 | + * | |
| 251 | + * @param obj An object whose field to get and set | |
| 252 | + * @param delta the value to add | |
| 253 | + * @return the updated value | |
| 254 | + */ | |
| 255 | + public long addAndGet(T obj, long delta) { | |
| 256 | + for (;;) { | |
| 257 | + long current = get(obj); | |
| 258 | + long next = current + delta; | |
| 259 | + if (compareAndSet(obj, current, next)) | |
| 260 | + return next; | |
| 261 | + } | |
| 262 | + } | |
| 263 | + | |
| 264 | + private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> { | |
| 265 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 266 | + private final long offset; | |
| 267 | + private final Class<T> tclass; | |
| 268 | + private final Class cclass; | |
| 269 | + | |
| 270 | + CASUpdater(Class<T> tclass, String fieldName) { | |
| 271 | + Field field = null; | |
| 272 | + Class caller = null; | |
| 273 | + int modifiers = 0; | |
| 274 | + try { | |
| 275 | + field = tclass.getDeclaredField(fieldName); | |
| 276 | + caller = sun.reflect.Reflection.getCallerClass(3); | |
| 277 | + modifiers = field.getModifiers(); | |
| 278 | + sun.reflect.misc.ReflectUtil.ensureMemberAccess( | |
| 279 | + caller, tclass, null, modifiers); | |
| 280 | + sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); | |
| 281 | + } catch (Exception ex) { | |
| 282 | + throw new RuntimeException(ex); | |
| 283 | + } | |
| 284 | + | |
| 285 | + Class fieldt = field.getType(); | |
| 286 | + if (fieldt != long.class) | |
| 287 | + throw new IllegalArgumentException("Must be long type"); | |
| 288 | + | |
| 289 | + if (!Modifier.isVolatile(modifiers)) | |
| 290 | + throw new IllegalArgumentException("Must be volatile type"); | |
| 291 | + | |
| 292 | + this.cclass = (Modifier.isProtected(modifiers) && | |
| 293 | + caller != tclass) ? caller : null; | |
| 294 | + this.tclass = tclass; | |
| 295 | + offset = unsafe.objectFieldOffset(field); | |
| 296 | + } | |
| 297 | + | |
| 298 | + private void fullCheck(T obj) { | |
| 299 | + if (!tclass.isInstance(obj)) | |
| 300 | + throw new ClassCastException(); | |
| 301 | + if (cclass != null) | |
| 302 | + ensureProtectedAccess(obj); | |
| 303 | + } | |
| 304 | + | |
| 305 | + public boolean compareAndSet(T obj, long expect, long update) { | |
| 306 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 307 | + return unsafe.compareAndSwapLong(obj, offset, expect, update); | |
| 308 | + } | |
| 309 | + | |
| 310 | + public boolean weakCompareAndSet(T obj, long expect, long update) { | |
| 311 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 312 | + return unsafe.compareAndSwapLong(obj, offset, expect, update); | |
| 313 | + } | |
| 314 | + | |
| 315 | + public void set(T obj, long newValue) { | |
| 316 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 317 | + unsafe.putLongVolatile(obj, offset, newValue); | |
| 318 | + } | |
| 319 | + | |
| 320 | + public void lazySet(T obj, long newValue) { | |
| 321 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 322 | + unsafe.putOrderedLong(obj, offset, newValue); | |
| 323 | + } | |
| 324 | + | |
| 325 | + public long get(T obj) { | |
| 326 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 327 | + return unsafe.getLongVolatile(obj, offset); | |
| 328 | + } | |
| 329 | + | |
| 330 | + private void ensureProtectedAccess(T obj) { | |
| 331 | + if (cclass.isInstance(obj)) { | |
| 332 | + return; | |
| 333 | + } | |
| 334 | + throw new RuntimeException( | |
| 335 | + new IllegalAccessException("Class " + | |
| 336 | + cclass.getName() + | |
| 337 | + " can not access a protected member of class " + | |
| 338 | + tclass.getName() + | |
| 339 | + " using an instance of " + | |
| 340 | + obj.getClass().getName() | |
| 341 | + ) | |
| 342 | + ); | |
| 343 | + } | |
| 344 | + } | |
| 345 | + | |
| 346 | + | |
| 347 | + private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { | |
| 348 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 349 | + private final long offset; | |
| 350 | + private final Class<T> tclass; | |
| 351 | + private final Class cclass; | |
| 352 | + | |
| 353 | + LockedUpdater(Class<T> tclass, String fieldName) { | |
| 354 | + Field field = null; | |
| 355 | + Class caller = null; | |
| 356 | + int modifiers = 0; | |
| 357 | + try { | |
| 358 | + field = tclass.getDeclaredField(fieldName); | |
| 359 | + caller = sun.reflect.Reflection.getCallerClass(3); | |
| 360 | + modifiers = field.getModifiers(); | |
| 361 | + sun.reflect.misc.ReflectUtil.ensureMemberAccess( | |
| 362 | + caller, tclass, null, modifiers); | |
| 363 | + sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); | |
| 364 | + } catch (Exception ex) { | |
| 365 | + throw new RuntimeException(ex); | |
| 366 | + } | |
| 367 | + | |
| 368 | + Class fieldt = field.getType(); | |
| 369 | + if (fieldt != long.class) | |
| 370 | + throw new IllegalArgumentException("Must be long type"); | |
| 371 | + | |
| 372 | + if (!Modifier.isVolatile(modifiers)) | |
| 373 | + throw new IllegalArgumentException("Must be volatile type"); | |
| 374 | + | |
| 375 | + this.cclass = (Modifier.isProtected(modifiers) && | |
| 376 | + caller != tclass) ? caller : null; | |
| 377 | + this.tclass = tclass; | |
| 378 | + offset = unsafe.objectFieldOffset(field); | |
| 379 | + } | |
| 380 | + | |
| 381 | + private void fullCheck(T obj) { | |
| 382 | + if (!tclass.isInstance(obj)) | |
| 383 | + throw new ClassCastException(); | |
| 384 | + if (cclass != null) | |
| 385 | + ensureProtectedAccess(obj); | |
| 386 | + } | |
| 387 | + | |
| 388 | + public boolean compareAndSet(T obj, long expect, long update) { | |
| 389 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 390 | + synchronized (this) { | |
| 391 | + long v = unsafe.getLong(obj, offset); | |
| 392 | + if (v != expect) | |
| 393 | + return false; | |
| 394 | + unsafe.putLong(obj, offset, update); | |
| 395 | + return true; | |
| 396 | + } | |
| 397 | + } | |
| 398 | + | |
| 399 | + public boolean weakCompareAndSet(T obj, long expect, long update) { | |
| 400 | + return compareAndSet(obj, expect, update); | |
| 401 | + } | |
| 402 | + | |
| 403 | + public void set(T obj, long newValue) { | |
| 404 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 405 | + synchronized (this) { | |
| 406 | + unsafe.putLong(obj, offset, newValue); | |
| 407 | + } | |
| 408 | + } | |
| 409 | + | |
| 410 | + public void lazySet(T obj, long newValue) { | |
| 411 | + set(obj, newValue); | |
| 412 | + } | |
| 413 | + | |
| 414 | + public long get(T obj) { | |
| 415 | + if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); | |
| 416 | + synchronized (this) { | |
| 417 | + return unsafe.getLong(obj, offset); | |
| 418 | + } | |
| 419 | + } | |
| 420 | + | |
| 421 | + private void ensureProtectedAccess(T obj) { | |
| 422 | + if (cclass.isInstance(obj)) { | |
| 423 | + return; | |
| 424 | + } | |
| 425 | + throw new RuntimeException( | |
| 426 | + new IllegalAccessException("Class " + | |
| 427 | + cclass.getName() + | |
| 428 | + " can not access a protected member of class " + | |
| 429 | + tclass.getName() + | |
| 430 | + " using an instance of " + | |
| 431 | + obj.getClass().getName() | |
| 432 | + ) | |
| 433 | + ); | |
| 434 | + } | |
| 435 | + } | |
| 436 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,212 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | + | |
| 38 | +/** | |
| 39 | + * An {@code AtomicMarkableReference} maintains an object reference | |
| 40 | + * along with a mark bit, that can be updated atomically. | |
| 41 | + * | |
| 42 | + * <p>Implementation note: This implementation maintains markable | |
| 43 | + * references by creating internal objects representing "boxed" | |
| 44 | + * [reference, boolean] pairs. | |
| 45 | + * | |
| 46 | + * @since 1.5 | |
| 47 | + * @author Doug Lea | |
| 48 | + * @param <V> The type of object referred to by this reference | |
| 49 | + */ | |
| 50 | +public class AtomicMarkableReference<V> { | |
| 51 | + | |
| 52 | + private static class Pair<T> { | |
| 53 | + final T reference; | |
| 54 | + final boolean mark; | |
| 55 | + private Pair(T reference, boolean mark) { | |
| 56 | + this.reference = reference; | |
| 57 | + this.mark = mark; | |
| 58 | + } | |
| 59 | + static <T> Pair<T> of(T reference, boolean mark) { | |
| 60 | + return new Pair<T>(reference, mark); | |
| 61 | + } | |
| 62 | + } | |
| 63 | + | |
| 64 | + private volatile Pair<V> pair; | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Creates a new {@code AtomicMarkableReference} with the given | |
| 68 | + * initial values. | |
| 69 | + * | |
| 70 | + * @param initialRef the initial reference | |
| 71 | + * @param initialMark the initial mark | |
| 72 | + */ | |
| 73 | + public AtomicMarkableReference(V initialRef, boolean initialMark) { | |
| 74 | + pair = Pair.of(initialRef, initialMark); | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Returns the current value of the reference. | |
| 79 | + * | |
| 80 | + * @return the current value of the reference | |
| 81 | + */ | |
| 82 | + public V getReference() { | |
| 83 | + return pair.reference; | |
| 84 | + } | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * Returns the current value of the mark. | |
| 88 | + * | |
| 89 | + * @return the current value of the mark | |
| 90 | + */ | |
| 91 | + public boolean isMarked() { | |
| 92 | + return pair.mark; | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Returns the current values of both the reference and the mark. | |
| 97 | + * Typical usage is {@code boolean[1] holder; ref = v.get(holder); }. | |
| 98 | + * | |
| 99 | + * @param markHolder an array of size of at least one. On return, | |
| 100 | + * {@code markholder[0]} will hold the value of the mark. | |
| 101 | + * @return the current value of the reference | |
| 102 | + */ | |
| 103 | + public V get(boolean[] markHolder) { | |
| 104 | + Pair<V> pair = this.pair; | |
| 105 | + markHolder[0] = pair.mark; | |
| 106 | + return pair.reference; | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * Atomically sets the value of both the reference and mark | |
| 111 | + * to the given update values if the | |
| 112 | + * current reference is {@code ==} to the expected reference | |
| 113 | + * and the current mark is equal to the expected mark. | |
| 114 | + * | |
| 115 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 116 | + * and does not provide ordering guarantees, so is only rarely an | |
| 117 | + * appropriate alternative to {@code compareAndSet}. | |
| 118 | + * | |
| 119 | + * @param expectedReference the expected value of the reference | |
| 120 | + * @param newReference the new value for the reference | |
| 121 | + * @param expectedMark the expected value of the mark | |
| 122 | + * @param newMark the new value for the mark | |
| 123 | + * @return true if successful | |
| 124 | + */ | |
| 125 | + public boolean weakCompareAndSet(V expectedReference, | |
| 126 | + V newReference, | |
| 127 | + boolean expectedMark, | |
| 128 | + boolean newMark) { | |
| 129 | + return compareAndSet(expectedReference, newReference, | |
| 130 | + expectedMark, newMark); | |
| 131 | + } | |
| 132 | + | |
| 133 | + /** | |
| 134 | + * Atomically sets the value of both the reference and mark | |
| 135 | + * to the given update values if the | |
| 136 | + * current reference is {@code ==} to the expected reference | |
| 137 | + * and the current mark is equal to the expected mark. | |
| 138 | + * | |
| 139 | + * @param expectedReference the expected value of the reference | |
| 140 | + * @param newReference the new value for the reference | |
| 141 | + * @param expectedMark the expected value of the mark | |
| 142 | + * @param newMark the new value for the mark | |
| 143 | + * @return true if successful | |
| 144 | + */ | |
| 145 | + public boolean compareAndSet(V expectedReference, | |
| 146 | + V newReference, | |
| 147 | + boolean expectedMark, | |
| 148 | + boolean newMark) { | |
| 149 | + Pair<V> current = pair; | |
| 150 | + return | |
| 151 | + expectedReference == current.reference && | |
| 152 | + expectedMark == current.mark && | |
| 153 | + ((newReference == current.reference && | |
| 154 | + newMark == current.mark) || | |
| 155 | + casPair(current, Pair.of(newReference, newMark))); | |
| 156 | + } | |
| 157 | + | |
| 158 | + /** | |
| 159 | + * Unconditionally sets the value of both the reference and mark. | |
| 160 | + * | |
| 161 | + * @param newReference the new value for the reference | |
| 162 | + * @param newMark the new value for the mark | |
| 163 | + */ | |
| 164 | + public void set(V newReference, boolean newMark) { | |
| 165 | + Pair<V> current = pair; | |
| 166 | + if (newReference != current.reference || newMark != current.mark) | |
| 167 | + this.pair = Pair.of(newReference, newMark); | |
| 168 | + } | |
| 169 | + | |
| 170 | + /** | |
| 171 | + * Atomically sets the value of the mark to the given update value | |
| 172 | + * if the current reference is {@code ==} to the expected | |
| 173 | + * reference. Any given invocation of this operation may fail | |
| 174 | + * (return {@code false}) spuriously, but repeated invocation | |
| 175 | + * when the current value holds the expected value and no other | |
| 176 | + * thread is also attempting to set the value will eventually | |
| 177 | + * succeed. | |
| 178 | + * | |
| 179 | + * @param expectedReference the expected value of the reference | |
| 180 | + * @param newMark the new value for the mark | |
| 181 | + * @return true if successful | |
| 182 | + */ | |
| 183 | + public boolean attemptMark(V expectedReference, boolean newMark) { | |
| 184 | + Pair<V> current = pair; | |
| 185 | + return | |
| 186 | + expectedReference == current.reference && | |
| 187 | + (newMark == current.mark || | |
| 188 | + casPair(current, Pair.of(expectedReference, newMark))); | |
| 189 | + } | |
| 190 | + | |
| 191 | + // Unsafe mechanics | |
| 192 | + | |
| 193 | + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); | |
| 194 | + private static final long pairOffset = | |
| 195 | + objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class); | |
| 196 | + | |
| 197 | + private boolean casPair(Pair<V> cmp, Pair<V> val) { | |
| 198 | + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); | |
| 199 | + } | |
| 200 | + | |
| 201 | + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, | |
| 202 | + String field, Class<?> klazz) { | |
| 203 | + try { | |
| 204 | + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); | |
| 205 | + } catch (NoSuchFieldException e) { | |
| 206 | + // Convert Exception to corresponding Error | |
| 207 | + NoSuchFieldError error = new NoSuchFieldError(field); | |
| 208 | + error.initCause(e); | |
| 209 | + throw error; | |
| 210 | + } | |
| 211 | + } | |
| 212 | +} | |
Binary file not shown.
| @@ -0,0 +1,155 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * An object reference that may be updated atomically. See the {@link | |
| 41 | + * java.util.concurrent.atomic} package specification for description | |
| 42 | + * of the properties of atomic variables. | |
| 43 | + * @since 1.5 | |
| 44 | + * @author Doug Lea | |
| 45 | + * @param <V> The type of object referred to by this reference | |
| 46 | + */ | |
| 47 | +public class AtomicReference<V> implements java.io.Serializable { | |
| 48 | + private static final long serialVersionUID = -1848883965231344442L; | |
| 49 | + | |
| 50 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 51 | + private static final long valueOffset; | |
| 52 | + | |
| 53 | + static { | |
| 54 | + try { | |
| 55 | + valueOffset = unsafe.objectFieldOffset | |
| 56 | + (AtomicReference.class.getDeclaredField("value")); | |
| 57 | + } catch (Exception ex) { throw new Error(ex); } | |
| 58 | + } | |
| 59 | + | |
| 60 | + private volatile V value; | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * Creates a new AtomicReference with the given initial value. | |
| 64 | + * | |
| 65 | + * @param initialValue the initial value | |
| 66 | + */ | |
| 67 | + public AtomicReference(V initialValue) { | |
| 68 | + value = initialValue; | |
| 69 | + } | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * Creates a new AtomicReference with null initial value. | |
| 73 | + */ | |
| 74 | + public AtomicReference() { | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Gets the current value. | |
| 79 | + * | |
| 80 | + * @return the current value | |
| 81 | + */ | |
| 82 | + public final V get() { | |
| 83 | + return value; | |
| 84 | + } | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * Sets to the given value. | |
| 88 | + * | |
| 89 | + * @param newValue the new value | |
| 90 | + */ | |
| 91 | + public final void set(V newValue) { | |
| 92 | + value = newValue; | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Eventually sets to the given value. | |
| 97 | + * | |
| 98 | + * @param newValue the new value | |
| 99 | + * @since 1.6 | |
| 100 | + */ | |
| 101 | + public final void lazySet(V newValue) { | |
| 102 | + unsafe.putOrderedObject(this, valueOffset, newValue); | |
| 103 | + } | |
| 104 | + | |
| 105 | + /** | |
| 106 | + * Atomically sets the value to the given updated value | |
| 107 | + * if the current value {@code ==} the expected value. | |
| 108 | + * @param expect the expected value | |
| 109 | + * @param update the new value | |
| 110 | + * @return true if successful. False return indicates that | |
| 111 | + * the actual value was not equal to the expected value. | |
| 112 | + */ | |
| 113 | + public final boolean compareAndSet(V expect, V update) { | |
| 114 | + return unsafe.compareAndSwapObject(this, valueOffset, expect, update); | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Atomically sets the value to the given updated value | |
| 119 | + * if the current value {@code ==} the expected value. | |
| 120 | + * | |
| 121 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 122 | + * and does not provide ordering guarantees, so is only rarely an | |
| 123 | + * appropriate alternative to {@code compareAndSet}. | |
| 124 | + * | |
| 125 | + * @param expect the expected value | |
| 126 | + * @param update the new value | |
| 127 | + * @return true if successful. | |
| 128 | + */ | |
| 129 | + public final boolean weakCompareAndSet(V expect, V update) { | |
| 130 | + return unsafe.compareAndSwapObject(this, valueOffset, expect, update); | |
| 131 | + } | |
| 132 | + | |
| 133 | + /** | |
| 134 | + * Atomically sets to the given value and returns the old value. | |
| 135 | + * | |
| 136 | + * @param newValue the new value | |
| 137 | + * @return the previous value | |
| 138 | + */ | |
| 139 | + public final V getAndSet(V newValue) { | |
| 140 | + while (true) { | |
| 141 | + V x = get(); | |
| 142 | + if (compareAndSet(x, newValue)) | |
| 143 | + return x; | |
| 144 | + } | |
| 145 | + } | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * Returns the String representation of the current value. | |
| 149 | + * @return the String representation of the current value. | |
| 150 | + */ | |
| 151 | + public String toString() { | |
| 152 | + return String.valueOf(get()); | |
| 153 | + } | |
| 154 | + | |
| 155 | +} | |
Binary file not shown.
| @@ -0,0 +1,213 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.util.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * An array of object references in which elements may be updated | |
| 42 | + * atomically. See the {@link java.util.concurrent.atomic} package | |
| 43 | + * specification for description of the properties of atomic | |
| 44 | + * variables. | |
| 45 | + * @since 1.5 | |
| 46 | + * @author Doug Lea | |
| 47 | + * @param <E> The base class of elements held in this array | |
| 48 | + */ | |
| 49 | +public class AtomicReferenceArray<E> implements java.io.Serializable { | |
| 50 | + private static final long serialVersionUID = -6209656149925076980L; | |
| 51 | + | |
| 52 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 53 | + private static final int base = unsafe.arrayBaseOffset(Object[].class); | |
| 54 | + private static final int shift; | |
| 55 | + private final Object[] array; | |
| 56 | + | |
| 57 | + static { | |
| 58 | + int scale = unsafe.arrayIndexScale(Object[].class); | |
| 59 | + if ((scale & (scale - 1)) != 0) | |
| 60 | + throw new Error("data type scale not a power of two"); | |
| 61 | + shift = 31 - Integer.numberOfLeadingZeros(scale); | |
| 62 | + } | |
| 63 | + | |
| 64 | + private long checkedByteOffset(int i) { | |
| 65 | + if (i < 0 || i >= array.length) | |
| 66 | + throw new IndexOutOfBoundsException("index " + i); | |
| 67 | + | |
| 68 | + return byteOffset(i); | |
| 69 | + } | |
| 70 | + | |
| 71 | + private static long byteOffset(int i) { | |
| 72 | + return ((long) i << shift) + base; | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Creates a new AtomicReferenceArray of the given length, with all | |
| 77 | + * elements initially null. | |
| 78 | + * | |
| 79 | + * @param length the length of the array | |
| 80 | + */ | |
| 81 | + public AtomicReferenceArray(int length) { | |
| 82 | + array = new Object[length]; | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Creates a new AtomicReferenceArray with the same length as, and | |
| 87 | + * all elements copied from, the given array. | |
| 88 | + * | |
| 89 | + * @param array the array to copy elements from | |
| 90 | + * @throws NullPointerException if array is null | |
| 91 | + */ | |
| 92 | + public AtomicReferenceArray(E[] array) { | |
| 93 | + // Visibility guaranteed by final field guarantees | |
| 94 | + this.array = array.clone(); | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Returns the length of the array. | |
| 99 | + * | |
| 100 | + * @return the length of the array | |
| 101 | + */ | |
| 102 | + public final int length() { | |
| 103 | + return array.length; | |
| 104 | + } | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * Gets the current value at position {@code i}. | |
| 108 | + * | |
| 109 | + * @param i the index | |
| 110 | + * @return the current value | |
| 111 | + */ | |
| 112 | + public final E get(int i) { | |
| 113 | + return getRaw(checkedByteOffset(i)); | |
| 114 | + } | |
| 115 | + | |
| 116 | + private E getRaw(long offset) { | |
| 117 | + return (E) unsafe.getObjectVolatile(array, offset); | |
| 118 | + } | |
| 119 | + | |
| 120 | + /** | |
| 121 | + * Sets the element at position {@code i} to the given value. | |
| 122 | + * | |
| 123 | + * @param i the index | |
| 124 | + * @param newValue the new value | |
| 125 | + */ | |
| 126 | + public final void set(int i, E newValue) { | |
| 127 | + unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); | |
| 128 | + } | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * Eventually sets the element at position {@code i} to the given value. | |
| 132 | + * | |
| 133 | + * @param i the index | |
| 134 | + * @param newValue the new value | |
| 135 | + * @since 1.6 | |
| 136 | + */ | |
| 137 | + public final void lazySet(int i, E newValue) { | |
| 138 | + unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); | |
| 139 | + } | |
| 140 | + | |
| 141 | + | |
| 142 | + /** | |
| 143 | + * Atomically sets the element at position {@code i} to the given | |
| 144 | + * value and returns the old value. | |
| 145 | + * | |
| 146 | + * @param i the index | |
| 147 | + * @param newValue the new value | |
| 148 | + * @return the previous value | |
| 149 | + */ | |
| 150 | + public final E getAndSet(int i, E newValue) { | |
| 151 | + long offset = checkedByteOffset(i); | |
| 152 | + while (true) { | |
| 153 | + E current = (E) getRaw(offset); | |
| 154 | + if (compareAndSetRaw(offset, current, newValue)) | |
| 155 | + return current; | |
| 156 | + } | |
| 157 | + } | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * Atomically sets the element at position {@code i} to the given | |
| 161 | + * updated value if the current value {@code ==} the expected value. | |
| 162 | + * | |
| 163 | + * @param i the index | |
| 164 | + * @param expect the expected value | |
| 165 | + * @param update the new value | |
| 166 | + * @return true if successful. False return indicates that | |
| 167 | + * the actual value was not equal to the expected value. | |
| 168 | + */ | |
| 169 | + public final boolean compareAndSet(int i, E expect, E update) { | |
| 170 | + return compareAndSetRaw(checkedByteOffset(i), expect, update); | |
| 171 | + } | |
| 172 | + | |
| 173 | + private boolean compareAndSetRaw(long offset, E expect, E update) { | |
| 174 | + return unsafe.compareAndSwapObject(array, offset, expect, update); | |
| 175 | + } | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * Atomically sets the element at position {@code i} to the given | |
| 179 | + * updated value if the current value {@code ==} the expected value. | |
| 180 | + * | |
| 181 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 182 | + * and does not provide ordering guarantees, so is only rarely an | |
| 183 | + * appropriate alternative to {@code compareAndSet}. | |
| 184 | + * | |
| 185 | + * @param i the index | |
| 186 | + * @param expect the expected value | |
| 187 | + * @param update the new value | |
| 188 | + * @return true if successful. | |
| 189 | + */ | |
| 190 | + public final boolean weakCompareAndSet(int i, E expect, E update) { | |
| 191 | + return compareAndSet(i, expect, update); | |
| 192 | + } | |
| 193 | + | |
| 194 | + /** | |
| 195 | + * Returns the String representation of the current values of array. | |
| 196 | + * @return the String representation of the current values of array | |
| 197 | + */ | |
| 198 | + public String toString() { | |
| 199 | + int iMax = array.length - 1; | |
| 200 | + if (iMax == -1) | |
| 201 | + return "[]"; | |
| 202 | + | |
| 203 | + StringBuilder b = new StringBuilder(); | |
| 204 | + b.append('['); | |
| 205 | + for (int i = 0; ; i++) { | |
| 206 | + b.append(getRaw(byteOffset(i))); | |
| 207 | + if (i == iMax) | |
| 208 | + return b.append(']').toString(); | |
| 209 | + b.append(',').append(' '); | |
| 210 | + } | |
| 211 | + } | |
| 212 | + | |
| 213 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,304 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | +import sun.misc.Unsafe; | |
| 38 | +import java.lang.reflect.*; | |
| 39 | + | |
| 40 | +/** | |
| 41 | + * A reflection-based utility that enables atomic updates to | |
| 42 | + * designated {@code volatile} reference fields of designated | |
| 43 | + * classes. This class is designed for use in atomic data structures | |
| 44 | + * in which several reference fields of the same node are | |
| 45 | + * independently subject to atomic updates. For example, a tree node | |
| 46 | + * might be declared as | |
| 47 | + * | |
| 48 | + * <pre> {@code | |
| 49 | + * class Node { | |
| 50 | + * private volatile Node left, right; | |
| 51 | + * | |
| 52 | + * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater = | |
| 53 | + * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left"); | |
| 54 | + * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = | |
| 55 | + * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); | |
| 56 | + * | |
| 57 | + * Node getLeft() { return left; } | |
| 58 | + * boolean compareAndSetLeft(Node expect, Node update) { | |
| 59 | + * return leftUpdater.compareAndSet(this, expect, update); | |
| 60 | + * } | |
| 61 | + * // ... and so on | |
| 62 | + * }}</pre> | |
| 63 | + * | |
| 64 | + * <p>Note that the guarantees of the {@code compareAndSet} | |
| 65 | + * method in this class are weaker than in other atomic classes. | |
| 66 | + * Because this class cannot ensure that all uses of the field | |
| 67 | + * are appropriate for purposes of atomic access, it can | |
| 68 | + * guarantee atomicity only with respect to other invocations of | |
| 69 | + * {@code compareAndSet} and {@code set} on the same updater. | |
| 70 | + * | |
| 71 | + * @since 1.5 | |
| 72 | + * @author Doug Lea | |
| 73 | + * @param <T> The type of the object holding the updatable field | |
| 74 | + * @param <V> The type of the field | |
| 75 | + */ | |
| 76 | +public abstract class AtomicReferenceFieldUpdater<T, V> { | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * Creates and returns an updater for objects with the given field. | |
| 80 | + * The Class arguments are needed to check that reflective types and | |
| 81 | + * generic types match. | |
| 82 | + * | |
| 83 | + * @param tclass the class of the objects holding the field. | |
| 84 | + * @param vclass the class of the field | |
| 85 | + * @param fieldName the name of the field to be updated. | |
| 86 | + * @return the updater | |
| 87 | + * @throws IllegalArgumentException if the field is not a volatile reference type. | |
| 88 | + * @throws RuntimeException with a nested reflection-based | |
| 89 | + * exception if the class does not hold field or is the wrong type. | |
| 90 | + */ | |
| 91 | + public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) { | |
| 92 | + return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass, | |
| 93 | + vclass, | |
| 94 | + fieldName); | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Protected do-nothing constructor for use by subclasses. | |
| 99 | + */ | |
| 100 | + protected AtomicReferenceFieldUpdater() { | |
| 101 | + } | |
| 102 | + | |
| 103 | + /** | |
| 104 | + * Atomically sets the field of the given object managed by this updater | |
| 105 | + * to the given updated value if the current value {@code ==} the | |
| 106 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 107 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 108 | + * necessarily with respect to other changes in the field. | |
| 109 | + * | |
| 110 | + * @param obj An object whose field to conditionally set | |
| 111 | + * @param expect the expected value | |
| 112 | + * @param update the new value | |
| 113 | + * @return true if successful. | |
| 114 | + */ | |
| 115 | + public abstract boolean compareAndSet(T obj, V expect, V update); | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Atomically sets the field of the given object managed by this updater | |
| 119 | + * to the given updated value if the current value {@code ==} the | |
| 120 | + * expected value. This method is guaranteed to be atomic with respect to | |
| 121 | + * other calls to {@code compareAndSet} and {@code set}, but not | |
| 122 | + * necessarily with respect to other changes in the field. | |
| 123 | + * | |
| 124 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 125 | + * and does not provide ordering guarantees, so is only rarely an | |
| 126 | + * appropriate alternative to {@code compareAndSet}. | |
| 127 | + * | |
| 128 | + * @param obj An object whose field to conditionally set | |
| 129 | + * @param expect the expected value | |
| 130 | + * @param update the new value | |
| 131 | + * @return true if successful. | |
| 132 | + */ | |
| 133 | + public abstract boolean weakCompareAndSet(T obj, V expect, V update); | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * Sets the field of the given object managed by this updater to the | |
| 137 | + * given updated value. This operation is guaranteed to act as a volatile | |
| 138 | + * store with respect to subsequent invocations of {@code compareAndSet}. | |
| 139 | + * | |
| 140 | + * @param obj An object whose field to set | |
| 141 | + * @param newValue the new value | |
| 142 | + */ | |
| 143 | + public abstract void set(T obj, V newValue); | |
| 144 | + | |
| 145 | + /** | |
| 146 | + * Eventually sets the field of the given object managed by this | |
| 147 | + * updater to the given updated value. | |
| 148 | + * | |
| 149 | + * @param obj An object whose field to set | |
| 150 | + * @param newValue the new value | |
| 151 | + * @since 1.6 | |
| 152 | + */ | |
| 153 | + public abstract void lazySet(T obj, V newValue); | |
| 154 | + | |
| 155 | + /** | |
| 156 | + * Gets the current value held in the field of the given object managed | |
| 157 | + * by this updater. | |
| 158 | + * | |
| 159 | + * @param obj An object whose field to get | |
| 160 | + * @return the current value | |
| 161 | + */ | |
| 162 | + public abstract V get(T obj); | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * Atomically sets the field of the given object managed by this updater | |
| 166 | + * to the given value and returns the old value. | |
| 167 | + * | |
| 168 | + * @param obj An object whose field to get and set | |
| 169 | + * @param newValue the new value | |
| 170 | + * @return the previous value | |
| 171 | + */ | |
| 172 | + public V getAndSet(T obj, V newValue) { | |
| 173 | + for (;;) { | |
| 174 | + V current = get(obj); | |
| 175 | + if (compareAndSet(obj, current, newValue)) | |
| 176 | + return current; | |
| 177 | + } | |
| 178 | + } | |
| 179 | + | |
| 180 | + private static final class AtomicReferenceFieldUpdaterImpl<T,V> | |
| 181 | + extends AtomicReferenceFieldUpdater<T,V> { | |
| 182 | + private static final Unsafe unsafe = Unsafe.getUnsafe(); | |
| 183 | + private final long offset; | |
| 184 | + private final Class<T> tclass; | |
| 185 | + private final Class<V> vclass; | |
| 186 | + private final Class cclass; | |
| 187 | + | |
| 188 | + /* | |
| 189 | + * Internal type checks within all update methods contain | |
| 190 | + * internal inlined optimizations checking for the common | |
| 191 | + * cases where the class is final (in which case a simple | |
| 192 | + * getClass comparison suffices) or is of type Object (in | |
| 193 | + * which case no check is needed because all objects are | |
| 194 | + * instances of Object). The Object case is handled simply by | |
| 195 | + * setting vclass to null in constructor. The targetCheck and | |
| 196 | + * updateCheck methods are invoked when these faster | |
| 197 | + * screenings fail. | |
| 198 | + */ | |
| 199 | + | |
| 200 | + AtomicReferenceFieldUpdaterImpl(Class<T> tclass, | |
| 201 | + Class<V> vclass, | |
| 202 | + String fieldName) { | |
| 203 | + Field field = null; | |
| 204 | + Class fieldClass = null; | |
| 205 | + Class caller = null; | |
| 206 | + int modifiers = 0; | |
| 207 | + try { | |
| 208 | + field = tclass.getDeclaredField(fieldName); | |
| 209 | + caller = sun.reflect.Reflection.getCallerClass(3); | |
| 210 | + modifiers = field.getModifiers(); | |
| 211 | + sun.reflect.misc.ReflectUtil.ensureMemberAccess( | |
| 212 | + caller, tclass, null, modifiers); | |
| 213 | + sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); | |
| 214 | + fieldClass = field.getType(); | |
| 215 | + } catch (Exception ex) { | |
| 216 | + throw new RuntimeException(ex); | |
| 217 | + } | |
| 218 | + | |
| 219 | + if (vclass != fieldClass) | |
| 220 | + throw new ClassCastException(); | |
| 221 | + | |
| 222 | + if (!Modifier.isVolatile(modifiers)) | |
| 223 | + throw new IllegalArgumentException("Must be volatile type"); | |
| 224 | + | |
| 225 | + this.cclass = (Modifier.isProtected(modifiers) && | |
| 226 | + caller != tclass) ? caller : null; | |
| 227 | + this.tclass = tclass; | |
| 228 | + if (vclass == Object.class) | |
| 229 | + this.vclass = null; | |
| 230 | + else | |
| 231 | + this.vclass = vclass; | |
| 232 | + offset = unsafe.objectFieldOffset(field); | |
| 233 | + } | |
| 234 | + | |
| 235 | + void targetCheck(T obj) { | |
| 236 | + if (!tclass.isInstance(obj)) | |
| 237 | + throw new ClassCastException(); | |
| 238 | + if (cclass != null) | |
| 239 | + ensureProtectedAccess(obj); | |
| 240 | + } | |
| 241 | + | |
| 242 | + void updateCheck(T obj, V update) { | |
| 243 | + if (!tclass.isInstance(obj) || | |
| 244 | + (update != null && vclass != null && !vclass.isInstance(update))) | |
| 245 | + throw new ClassCastException(); | |
| 246 | + if (cclass != null) | |
| 247 | + ensureProtectedAccess(obj); | |
| 248 | + } | |
| 249 | + | |
| 250 | + public boolean compareAndSet(T obj, V expect, V update) { | |
| 251 | + if (obj == null || obj.getClass() != tclass || cclass != null || | |
| 252 | + (update != null && vclass != null && | |
| 253 | + vclass != update.getClass())) | |
| 254 | + updateCheck(obj, update); | |
| 255 | + return unsafe.compareAndSwapObject(obj, offset, expect, update); | |
| 256 | + } | |
| 257 | + | |
| 258 | + public boolean weakCompareAndSet(T obj, V expect, V update) { | |
| 259 | + // same implementation as strong form for now | |
| 260 | + if (obj == null || obj.getClass() != tclass || cclass != null || | |
| 261 | + (update != null && vclass != null && | |
| 262 | + vclass != update.getClass())) | |
| 263 | + updateCheck(obj, update); | |
| 264 | + return unsafe.compareAndSwapObject(obj, offset, expect, update); | |
| 265 | + } | |
| 266 | + | |
| 267 | + public void set(T obj, V newValue) { | |
| 268 | + if (obj == null || obj.getClass() != tclass || cclass != null || | |
| 269 | + (newValue != null && vclass != null && | |
| 270 | + vclass != newValue.getClass())) | |
| 271 | + updateCheck(obj, newValue); | |
| 272 | + unsafe.putObjectVolatile(obj, offset, newValue); | |
| 273 | + } | |
| 274 | + | |
| 275 | + public void lazySet(T obj, V newValue) { | |
| 276 | + if (obj == null || obj.getClass() != tclass || cclass != null || | |
| 277 | + (newValue != null && vclass != null && | |
| 278 | + vclass != newValue.getClass())) | |
| 279 | + updateCheck(obj, newValue); | |
| 280 | + unsafe.putOrderedObject(obj, offset, newValue); | |
| 281 | + } | |
| 282 | + | |
| 283 | + public V get(T obj) { | |
| 284 | + if (obj == null || obj.getClass() != tclass || cclass != null) | |
| 285 | + targetCheck(obj); | |
| 286 | + return (V)unsafe.getObjectVolatile(obj, offset); | |
| 287 | + } | |
| 288 | + | |
| 289 | + private void ensureProtectedAccess(T obj) { | |
| 290 | + if (cclass.isInstance(obj)) { | |
| 291 | + return; | |
| 292 | + } | |
| 293 | + throw new RuntimeException( | |
| 294 | + new IllegalAccessException("Class " + | |
| 295 | + cclass.getName() + | |
| 296 | + " can not access a protected member of class " + | |
| 297 | + tclass.getName() + | |
| 298 | + " using an instance of " + | |
| 299 | + obj.getClass().getName() | |
| 300 | + ) | |
| 301 | + ); | |
| 302 | + } | |
| 303 | + } | |
| 304 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -0,0 +1,213 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +package java.util.concurrent.atomic; | |
| 37 | + | |
| 38 | +/** | |
| 39 | + * An {@code AtomicStampedReference} maintains an object reference | |
| 40 | + * along with an integer "stamp", that can be updated atomically. | |
| 41 | + * | |
| 42 | + * <p>Implementation note: This implementation maintains stamped | |
| 43 | + * references by creating internal objects representing "boxed" | |
| 44 | + * [reference, integer] pairs. | |
| 45 | + * | |
| 46 | + * @since 1.5 | |
| 47 | + * @author Doug Lea | |
| 48 | + * @param <V> The type of object referred to by this reference | |
| 49 | + */ | |
| 50 | +public class AtomicStampedReference<V> { | |
| 51 | + | |
| 52 | + private static class Pair<T> { | |
| 53 | + final T reference; | |
| 54 | + final int stamp; | |
| 55 | + private Pair(T reference, int stamp) { | |
| 56 | + this.reference = reference; | |
| 57 | + this.stamp = stamp; | |
| 58 | + } | |
| 59 | + static <T> Pair<T> of(T reference, int stamp) { | |
| 60 | + return new Pair<T>(reference, stamp); | |
| 61 | + } | |
| 62 | + } | |
| 63 | + | |
| 64 | + private volatile Pair<V> pair; | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Creates a new {@code AtomicStampedReference} with the given | |
| 68 | + * initial values. | |
| 69 | + * | |
| 70 | + * @param initialRef the initial reference | |
| 71 | + * @param initialStamp the initial stamp | |
| 72 | + */ | |
| 73 | + public AtomicStampedReference(V initialRef, int initialStamp) { | |
| 74 | + pair = Pair.of(initialRef, initialStamp); | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Returns the current value of the reference. | |
| 79 | + * | |
| 80 | + * @return the current value of the reference | |
| 81 | + */ | |
| 82 | + public V getReference() { | |
| 83 | + return pair.reference; | |
| 84 | + } | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * Returns the current value of the stamp. | |
| 88 | + * | |
| 89 | + * @return the current value of the stamp | |
| 90 | + */ | |
| 91 | + public int getStamp() { | |
| 92 | + return pair.stamp; | |
| 93 | + } | |
| 94 | + | |
| 95 | + /** | |
| 96 | + * Returns the current values of both the reference and the stamp. | |
| 97 | + * Typical usage is {@code int[1] holder; ref = v.get(holder); }. | |
| 98 | + * | |
| 99 | + * @param stampHolder an array of size of at least one. On return, | |
| 100 | + * {@code stampholder[0]} will hold the value of the stamp. | |
| 101 | + * @return the current value of the reference | |
| 102 | + */ | |
| 103 | + public V get(int[] stampHolder) { | |
| 104 | + Pair<V> pair = this.pair; | |
| 105 | + stampHolder[0] = pair.stamp; | |
| 106 | + return pair.reference; | |
| 107 | + } | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * Atomically sets the value of both the reference and stamp | |
| 111 | + * to the given update values if the | |
| 112 | + * current reference is {@code ==} to the expected reference | |
| 113 | + * and the current stamp is equal to the expected stamp. | |
| 114 | + * | |
| 115 | + * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> | |
| 116 | + * and does not provide ordering guarantees, so is only rarely an | |
| 117 | + * appropriate alternative to {@code compareAndSet}. | |
| 118 | + * | |
| 119 | + * @param expectedReference the expected value of the reference | |
| 120 | + * @param newReference the new value for the reference | |
| 121 | + * @param expectedStamp the expected value of the stamp | |
| 122 | + * @param newStamp the new value for the stamp | |
| 123 | + * @return true if successful | |
| 124 | + */ | |
| 125 | + public boolean weakCompareAndSet(V expectedReference, | |
| 126 | + V newReference, | |
| 127 | + int expectedStamp, | |
| 128 | + int newStamp) { | |
| 129 | + return compareAndSet(expectedReference, newReference, | |
| 130 | + expectedStamp, newStamp); | |
| 131 | + } | |
| 132 | + | |
| 133 | + /** | |
| 134 | + * Atomically sets the value of both the reference and stamp | |
| 135 | + * to the given update values if the | |
| 136 | + * current reference is {@code ==} to the expected reference | |
| 137 | + * and the current stamp is equal to the expected stamp. | |
| 138 | + * | |
| 139 | + * @param expectedReference the expected value of the reference | |
| 140 | + * @param newReference the new value for the reference | |
| 141 | + * @param expectedStamp the expected value of the stamp | |
| 142 | + * @param newStamp the new value for the stamp | |
| 143 | + * @return true if successful | |
| 144 | + */ | |
| 145 | + public boolean compareAndSet(V expectedReference, | |
| 146 | + V newReference, | |
| 147 | + int expectedStamp, | |
| 148 | + int newStamp) { | |
| 149 | + Pair<V> current = pair; | |
| 150 | + return | |
| 151 | + expectedReference == current.reference && | |
| 152 | + expectedStamp == current.stamp && | |
| 153 | + ((newReference == current.reference && | |
| 154 | + newStamp == current.stamp) || | |
| 155 | + casPair(current, Pair.of(newReference, newStamp))); | |
| 156 | + } | |
| 157 | + | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * Unconditionally sets the value of both the reference and stamp. | |
| 161 | + * | |
| 162 | + * @param newReference the new value for the reference | |
| 163 | + * @param newStamp the new value for the stamp | |
| 164 | + */ | |
| 165 | + public void set(V newReference, int newStamp) { | |
| 166 | + Pair<V> current = pair; | |
| 167 | + if (newReference != current.reference || newStamp != current.stamp) | |
| 168 | + this.pair = Pair.of(newReference, newStamp); | |
| 169 | + } | |
| 170 | + | |
| 171 | + /** | |
| 172 | + * Atomically sets the value of the stamp to the given update value | |
| 173 | + * if the current reference is {@code ==} to the expected | |
| 174 | + * reference. Any given invocation of this operation may fail | |
| 175 | + * (return {@code false}) spuriously, but repeated invocation | |
| 176 | + * when the current value holds the expected value and no other | |
| 177 | + * thread is also attempting to set the value will eventually | |
| 178 | + * succeed. | |
| 179 | + * | |
| 180 | + * @param expectedReference the expected value of the reference | |
| 181 | + * @param newStamp the new value for the stamp | |
| 182 | + * @return true if successful | |
| 183 | + */ | |
| 184 | + public boolean attemptStamp(V expectedReference, int newStamp) { | |
| 185 | + Pair<V> current = pair; | |
| 186 | + return | |
| 187 | + expectedReference == current.reference && | |
| 188 | + (newStamp == current.stamp || | |
| 189 | + casPair(current, Pair.of(expectedReference, newStamp))); | |
| 190 | + } | |
| 191 | + | |
| 192 | + // Unsafe mechanics | |
| 193 | + | |
| 194 | + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); | |
| 195 | + private static final long pairOffset = | |
| 196 | + objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); | |
| 197 | + | |
| 198 | + private boolean casPair(Pair<V> cmp, Pair<V> val) { | |
| 199 | + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); | |
| 200 | + } | |
| 201 | + | |
| 202 | + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, | |
| 203 | + String field, Class<?> klazz) { | |
| 204 | + try { | |
| 205 | + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); | |
| 206 | + } catch (NoSuchFieldException e) { | |
| 207 | + // Convert Exception to corresponding Error | |
| 208 | + NoSuchFieldError error = new NoSuchFieldError(field); | |
| 209 | + error.initCause(e); | |
| 210 | + throw error; | |
| 211 | + } | |
| 212 | + } | |
| 213 | +} | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +<../../../../../../mkconfig | |
| 2 | + | |
| 3 | +TARG=\ | |
| 4 | + AtomicBoolean.dis\ | |
| 5 | + AtomicInteger.dis\ | |
| 6 | + AtomicIntegerArray.dis\ | |
| 7 | + AtomicIntegerFieldUpdater.dis\ | |
| 8 | + AtomicLong.dis\ | |
| 9 | + AtomicLongArray.dis\ | |
| 10 | + AtomicLongFieldUpdater.dis\ | |
| 11 | + AtomicMarkableReference.dis\ | |
| 12 | + AtomicReference.dis\ | |
| 13 | + AtomicReferenceArray.dis\ | |
| 14 | + AtomicReferenceFieldUpdater.dis\ | |
| 15 | + AtomicStampedReference.dis\ | |
| 16 | + package-info.dis\ | |
| 17 | + | |
| 18 | +DISBIN=$ROOT/java/dis/java/java/java/util/concurrent/atomic | |
| 19 | + | |
| 20 | +<$ROOT/mkfiles/mkjava | |
| @@ -0,0 +1,199 @@ | ||
| 1 | +/* | |
| 2 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| 3 | + * | |
| 4 | + * This code is free software; you can redistribute it and/or modify it | |
| 5 | + * under the terms of the GNU General Public License version 2 only, as | |
| 6 | + * published by the Free Software Foundation. Oracle designates this | |
| 7 | + * particular file as subject to the "Classpath" exception as provided | |
| 8 | + * by Oracle in the LICENSE file that accompanied this code. | |
| 9 | + * | |
| 10 | + * This code is distributed in the hope that it will be useful, but WITHOUT | |
| 11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 13 | + * version 2 for more details (a copy is included in the LICENSE file that | |
| 14 | + * accompanied this code). | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License version | |
| 17 | + * 2 along with this work; if not, write to the Free Software Foundation, | |
| 18 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 19 | + * | |
| 20 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| 21 | + * or visit www.oracle.com if you need additional information or have any | |
| 22 | + * questions. | |
| 23 | + */ | |
| 24 | + | |
| 25 | +/* | |
| 26 | + * This file is available under and governed by the GNU General Public | |
| 27 | + * License version 2 only, as published by the Free Software Foundation. | |
| 28 | + * However, the following notice accompanied the original version of this | |
| 29 | + * file: | |
| 30 | + * | |
| 31 | + * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| 32 | + * Expert Group and released to the public domain, as explained at | |
| 33 | + * http://creativecommons.org/publicdomain/zero/1.0/ | |
| 34 | + */ | |
| 35 | + | |
| 36 | +/** | |
| 37 | + * A small toolkit of classes that support lock-free thread-safe | |
| 38 | + * programming on single variables. In essence, the classes in this | |
| 39 | + * package extend the notion of {@code volatile} values, fields, and | |
| 40 | + * array elements to those that also provide an atomic conditional update | |
| 41 | + * operation of the form: | |
| 42 | + * | |
| 43 | + * <pre> | |
| 44 | + * boolean compareAndSet(expectedValue, updateValue); | |
| 45 | + * </pre> | |
| 46 | + * | |
| 47 | + * <p>This method (which varies in argument types across different | |
| 48 | + * classes) atomically sets a variable to the {@code updateValue} if it | |
| 49 | + * currently holds the {@code expectedValue}, reporting {@code true} on | |
| 50 | + * success. The classes in this package also contain methods to get and | |
| 51 | + * unconditionally set values, as well as a weaker conditional atomic | |
| 52 | + * update operation {@code weakCompareAndSet} described below. | |
| 53 | + * | |
| 54 | + * <p>The specifications of these methods enable implementations to | |
| 55 | + * employ efficient machine-level atomic instructions that are available | |
| 56 | + * on contemporary processors. However on some platforms, support may | |
| 57 | + * entail some form of internal locking. Thus the methods are not | |
| 58 | + * strictly guaranteed to be non-blocking -- | |
| 59 | + * a thread may block transiently before performing the operation. | |
| 60 | + * | |
| 61 | + * <p>Instances of classes | |
| 62 | + * {@link java.util.concurrent.atomic.AtomicBoolean}, | |
| 63 | + * {@link java.util.concurrent.atomic.AtomicInteger}, | |
| 64 | + * {@link java.util.concurrent.atomic.AtomicLong}, and | |
| 65 | + * {@link java.util.concurrent.atomic.AtomicReference} | |
| 66 | + * each provide access and updates to a single variable of the | |
| 67 | + * corresponding type. Each class also provides appropriate utility | |
| 68 | + * methods for that type. For example, classes {@code AtomicLong} and | |
| 69 | + * {@code AtomicInteger} provide atomic increment methods. One | |
| 70 | + * application is to generate sequence numbers, as in: | |
| 71 | + * | |
| 72 | + * <pre> | |
| 73 | + * class Sequencer { | |
| 74 | + * private final AtomicLong sequenceNumber | |
| 75 | + * = new AtomicLong(0); | |
| 76 | + * public long next() { | |
| 77 | + * return sequenceNumber.getAndIncrement(); | |
| 78 | + * } | |
| 79 | + * } | |
| 80 | + * </pre> | |
| 81 | + * | |
| 82 | + * <p>The memory effects for accesses and updates of atomics generally | |
| 83 | + * follow the rules for volatiles, as stated in section 17.4 of | |
| 84 | + * <cite>The Java™ Language Specification</cite>. | |
| 85 | + * | |
| 86 | + * <ul> | |
| 87 | + * | |
| 88 | + * <li> {@code get} has the memory effects of reading a | |
| 89 | + * {@code volatile} variable. | |
| 90 | + * | |
| 91 | + * <li> {@code set} has the memory effects of writing (assigning) a | |
| 92 | + * {@code volatile} variable. | |
| 93 | + * | |
| 94 | + * <li> {@code lazySet} has the memory effects of writing (assigning) | |
| 95 | + * a {@code volatile} variable except that it permits reorderings with | |
| 96 | + * subsequent (but not previous) memory actions that do not themselves | |
| 97 | + * impose reordering constraints with ordinary non-{@code volatile} | |
| 98 | + * writes. Among other usage contexts, {@code lazySet} may apply when | |
| 99 | + * nulling out, for the sake of garbage collection, a reference that is | |
| 100 | + * never accessed again. | |
| 101 | + * | |
| 102 | + * <li>{@code weakCompareAndSet} atomically reads and conditionally | |
| 103 | + * writes a variable but does <em>not</em> | |
| 104 | + * create any happens-before orderings, so provides no guarantees | |
| 105 | + * with respect to previous or subsequent reads and writes of any | |
| 106 | + * variables other than the target of the {@code weakCompareAndSet}. | |
| 107 | + * | |
| 108 | + * <li> {@code compareAndSet} | |
| 109 | + * and all other read-and-update operations such as {@code getAndIncrement} | |
| 110 | + * have the memory effects of both reading and | |
| 111 | + * writing {@code volatile} variables. | |
| 112 | + * </ul> | |
| 113 | + * | |
| 114 | + * <p>In addition to classes representing single values, this package | |
| 115 | + * contains <em>Updater</em> classes that can be used to obtain | |
| 116 | + * {@code compareAndSet} operations on any selected {@code volatile} | |
| 117 | + * field of any selected class. | |
| 118 | + * | |
| 119 | + * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater}, | |
| 120 | + * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and | |
| 121 | + * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are | |
| 122 | + * reflection-based utilities that provide access to the associated | |
| 123 | + * field types. These are mainly of use in atomic data structures in | |
| 124 | + * which several {@code volatile} fields of the same node (for | |
| 125 | + * example, the links of a tree node) are independently subject to | |
| 126 | + * atomic updates. These classes enable greater flexibility in how | |
| 127 | + * and when to use atomic updates, at the expense of more awkward | |
| 128 | + * reflection-based setup, less convenient usage, and weaker | |
| 129 | + * guarantees. | |
| 130 | + * | |
| 131 | + * <p>The | |
| 132 | + * {@link java.util.concurrent.atomic.AtomicIntegerArray}, | |
| 133 | + * {@link java.util.concurrent.atomic.AtomicLongArray}, and | |
| 134 | + * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes | |
| 135 | + * further extend atomic operation support to arrays of these types. | |
| 136 | + * These classes are also notable in providing {@code volatile} access | |
| 137 | + * semantics for their array elements, which is not supported for | |
| 138 | + * ordinary arrays. | |
| 139 | + * | |
| 140 | + * <a name="Spurious"> | |
| 141 | + * <p>The atomic classes also support method {@code weakCompareAndSet}, | |
| 142 | + * which has limited applicability. On some platforms, the weak version | |
| 143 | + * may be more efficient than {@code compareAndSet} in the normal case, | |
| 144 | + * but differs in that any given invocation of the | |
| 145 | + * {@code weakCompareAndSet} method may return {@code false} | |
| 146 | + * <em>spuriously</em> (that is, for no apparent reason)</a>. A | |
| 147 | + * {@code false} return means only that the operation may be retried if | |
| 148 | + * desired, relying on the guarantee that repeated invocation when the | |
| 149 | + * variable holds {@code expectedValue} and no other thread is also | |
| 150 | + * attempting to set the variable will eventually succeed. (Such | |
| 151 | + * spurious failures may for example be due to memory contention effects | |
| 152 | + * that are unrelated to whether the expected and current values are | |
| 153 | + * equal.) Additionally {@code weakCompareAndSet} does not provide | |
| 154 | + * ordering guarantees that are usually needed for synchronization | |
| 155 | + * control. However, the method may be useful for updating counters and | |
| 156 | + * statistics when such updates are unrelated to the other | |
| 157 | + * happens-before orderings of a program. When a thread sees an update | |
| 158 | + * to an atomic variable caused by a {@code weakCompareAndSet}, it does | |
| 159 | + * not necessarily see updates to any <em>other</em> variables that | |
| 160 | + * occurred before the {@code weakCompareAndSet}. This may be | |
| 161 | + * acceptable when, for example, updating performance statistics, but | |
| 162 | + * rarely otherwise. | |
| 163 | + * | |
| 164 | + * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference} | |
| 165 | + * class associates a single boolean with a reference. For example, this | |
| 166 | + * bit might be used inside a data structure to mean that the object | |
| 167 | + * being referenced has logically been deleted. | |
| 168 | + * | |
| 169 | + * The {@link java.util.concurrent.atomic.AtomicStampedReference} | |
| 170 | + * class associates an integer value with a reference. This may be | |
| 171 | + * used for example, to represent version numbers corresponding to | |
| 172 | + * series of updates. | |
| 173 | + * | |
| 174 | + * <p>Atomic classes are designed primarily as building blocks for | |
| 175 | + * implementing non-blocking data structures and related infrastructure | |
| 176 | + * classes. The {@code compareAndSet} method is not a general | |
| 177 | + * replacement for locking. It applies only when critical updates for an | |
| 178 | + * object are confined to a <em>single</em> variable. | |
| 179 | + * | |
| 180 | + * <p>Atomic classes are not general purpose replacements for | |
| 181 | + * {@code java.lang.Integer} and related classes. They do <em>not</em> | |
| 182 | + * define methods such as {@code hashCode} and | |
| 183 | + * {@code compareTo}. (Because atomic variables are expected to be | |
| 184 | + * mutated, they are poor choices for hash table keys.) Additionally, | |
| 185 | + * classes are provided only for those types that are commonly useful in | |
| 186 | + * intended applications. For example, there is no atomic class for | |
| 187 | + * representing {@code byte}. In those infrequent cases where you would | |
| 188 | + * like to do so, you can use an {@code AtomicInteger} to hold | |
| 189 | + * {@code byte} values, and cast appropriately. | |
| 190 | + * | |
| 191 | + * You can also hold floats using | |
| 192 | + * {@link java.lang.Float#floatToIntBits} and | |
| 193 | + * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using | |
| 194 | + * {@link java.lang.Double#doubleToLongBits} and | |
| 195 | + * {@link java.lang.Double#longBitsToDouble} conversions. | |
| 196 | + * | |
| 197 | + * @since 1.5 | |
| 198 | + */ | |
| 199 | +package java.util.concurrent.atomic; | |