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; | ||