001: /*
002: * Written by Doug Lea with assistance from members of JCP JSR-166
003: * Expert Group and released to the public domain, as explained at
004: * http://creativecommons.org/licenses/publicdomain
005: */
006:
007: package java.util.concurrent.atomic;
008:
009: import sun.misc.Unsafe;
010:
011: /**
012: * A <tt>long</tt> value that may be updated atomically. See the
013: * {@link java.util.concurrent.atomic} package specification for
014: * description of the properties of atomic variables. An
015: * <tt>AtomicLong</tt> is used in applications such as atomically
016: * incremented sequence numbers, and cannot be used as a replacement
017: * for a {@link java.lang.Long}. However, this class does extend
018: * <tt>Number</tt> to allow uniform access by tools and utilities that
019: * deal with numerically-based classes.
020: *
021: * @since 1.5
022: * @author Doug Lea
023: */
024: public class AtomicLong extends Number implements java.io.Serializable {
025: private static final long serialVersionUID = 1927816293512124184L;
026:
027: // setup to use Unsafe.compareAndSwapLong for updates
028: private static final Unsafe unsafe = Unsafe.getUnsafe();
029: private static final long valueOffset;
030:
031: /**
032: * Record whether the underlying JVM supports lockless
033: * CompareAndSet for longs. While the unsafe.CompareAndSetLong
034: * method works in either case, some constructions should be
035: * handled at Java level to avoid locking user-visible locks.
036: */
037: static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
038:
039: /**
040: * Returns whether underlying JVM supports lockless CompareAndSet
041: * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
042: */
043: private static native boolean VMSupportsCS8();
044:
045: static {
046: try {
047: valueOffset = unsafe.objectFieldOffset(AtomicLong.class
048: .getDeclaredField("value"));
049: } catch (Exception ex) {
050: throw new Error(ex);
051: }
052: }
053:
054: private volatile long value;
055:
056: /**
057: * Create a new AtomicLong with the given initial value.
058: *
059: * @param initialValue the initial value
060: */
061: public AtomicLong(long initialValue) {
062: value = initialValue;
063: }
064:
065: /**
066: * Create a new AtomicLong with initial value <tt>0</tt>.
067: */
068: public AtomicLong() {
069: }
070:
071: /**
072: * Get the current value.
073: *
074: * @return the current value
075: */
076: public final long get() {
077: return value;
078: }
079:
080: /**
081: * Set to the given value.
082: *
083: * @param newValue the new value
084: */
085: public final void set(long newValue) {
086: value = newValue;
087: }
088:
089: /**
090: * Set to the give value and return the old value.
091: *
092: * @param newValue the new value
093: * @return the previous value
094: */
095: public final long getAndSet(long newValue) {
096: while (true) {
097: long current = get();
098: if (compareAndSet(current, newValue))
099: return current;
100: }
101: }
102:
103: /**
104: * Atomically set the value to the given updated value
105: * if the current value <tt>==</tt> the expected value.
106: * @param expect the expected value
107: * @param update the new value
108: * @return true if successful. False return indicates that
109: * the actual value was not equal to the expected value.
110: */
111: public final boolean compareAndSet(long expect, long update) {
112: return unsafe.compareAndSwapLong(this , valueOffset, expect,
113: update);
114: }
115:
116: /**
117: * Atomically set the value to the given updated value
118: * if the current value <tt>==</tt> the expected value.
119: * May fail spuriously.
120: * @param expect the expected value
121: * @param update the new value
122: * @return true if successful.
123: */
124: public final boolean weakCompareAndSet(long expect, long update) {
125: return unsafe.compareAndSwapLong(this , valueOffset, expect,
126: update);
127: }
128:
129: /**
130: * Atomically increment by one the current value.
131: * @return the previous value
132: */
133: public final long getAndIncrement() {
134: while (true) {
135: long current = get();
136: long next = current + 1;
137: if (compareAndSet(current, next))
138: return current;
139: }
140: }
141:
142: /**
143: * Atomically decrement by one the current value.
144: * @return the previous value
145: */
146: public final long getAndDecrement() {
147: while (true) {
148: long current = get();
149: long next = current - 1;
150: if (compareAndSet(current, next))
151: return current;
152: }
153: }
154:
155: /**
156: * Atomically add the given value to current value.
157: * @param delta the value to add
158: * @return the previous value
159: */
160: public final long getAndAdd(long delta) {
161: while (true) {
162: long current = get();
163: long next = current + delta;
164: if (compareAndSet(current, next))
165: return current;
166: }
167: }
168:
169: /**
170: * Atomically increment by one the current value.
171: * @return the updated value
172: */
173: public final long incrementAndGet() {
174: for (;;) {
175: long current = get();
176: long next = current + 1;
177: if (compareAndSet(current, next))
178: return next;
179: }
180: }
181:
182: /**
183: * Atomically decrement by one the current value.
184: * @return the updated value
185: */
186: public final long decrementAndGet() {
187: for (;;) {
188: long current = get();
189: long next = current - 1;
190: if (compareAndSet(current, next))
191: return next;
192: }
193: }
194:
195: /**
196: * Atomically add the given value to current value.
197: * @param delta the value to add
198: * @return the updated value
199: */
200: public final long addAndGet(long delta) {
201: for (;;) {
202: long current = get();
203: long next = current + delta;
204: if (compareAndSet(current, next))
205: return next;
206: }
207: }
208:
209: /**
210: * Returns the String representation of the current value.
211: * @return the String representation of the current value.
212: */
213: public String toString() {
214: return Long.toString(get());
215: }
216:
217: public int intValue() {
218: return (int) get();
219: }
220:
221: public long longValue() {
222: return (long) get();
223: }
224:
225: public float floatValue() {
226: return (float) get();
227: }
228:
229: public double doubleValue() {
230: return (double) get();
231: }
232:
233: }
|