OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / classpath / external / jsr166 / java / util / concurrent / atomic / AtomicLong.java
1 /*
2  * Written by Doug Lea with assistance from members of JCP JSR-166
3  * Expert Group and released to the public domain, as explained at
4  * http://creativecommons.org/licenses/publicdomain
5  */
6
7 package java.util.concurrent.atomic;
8 import sun.misc.Unsafe;
9
10 /**
11  * A <tt>long</tt> value that may be updated atomically.  See the
12  * {@link java.util.concurrent.atomic} package specification for
13  * description of the properties of atomic variables. An
14  * <tt>AtomicLong</tt> is used in applications such as atomically
15  * incremented sequence numbers, and cannot be used as a replacement
16  * for a {@link java.lang.Long}. However, this class does extend
17  * <tt>Number</tt> to allow uniform access by tools and utilities that
18  * deal with numerically-based classes.
19  *
20  * @since 1.5
21  * @author Doug Lea
22  */
23 public class AtomicLong extends Number implements java.io.Serializable {
24     private static final long serialVersionUID = 1927816293512124184L;
25
26     // setup to use Unsafe.compareAndSwapLong for updates
27     private static final Unsafe unsafe = Unsafe.getUnsafe();
28     private static final long valueOffset;
29
30     /**
31      * Records whether the underlying JVM supports lockless
32      * CompareAndSet for longs. While the unsafe.CompareAndSetLong
33      * method works in either case, some constructions should be
34      * handled at Java level to avoid locking user-visible locks.
35      */
36     static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
37
38     /**
39      * Returns whether underlying JVM supports lockless CompareAndSet
40      * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
41      */
42     private static native boolean VMSupportsCS8();
43
44     static {
45       try {
46         valueOffset = unsafe.objectFieldOffset
47             (AtomicLong.class.getDeclaredField("value"));
48       } catch (Exception ex) { throw new Error(ex); }
49     }
50
51     private volatile long value;
52
53     /**
54      * Creates a new AtomicLong with the given initial value.
55      *
56      * @param initialValue the initial value
57      */
58     public AtomicLong(long initialValue) {
59         value = initialValue;
60     }
61
62     /**
63      * Creates a new AtomicLong with initial value <tt>0</tt>.
64      */
65     public AtomicLong() {
66     }
67
68     /**
69      * Gets the current value.
70      *
71      * @return the current value
72      */
73     public final long get() {
74         return value;
75     }
76
77     /**
78      * Sets to the given value.
79      *
80      * @param newValue the new value
81      */
82     public final void set(long newValue) {
83         value = newValue;
84     }
85
86     /**
87      * Eventually sets to the given value.
88      *
89      * @param newValue the new value
90      * @since 1.6
91      */
92     public final void lazySet(long newValue) {
93         unsafe.putOrderedLong(this, valueOffset, newValue);
94     }
95
96     /**
97      * Atomically sets to the given value and returns the old value.
98      *
99      * @param newValue the new value
100      * @return the previous value
101      */
102     public final long getAndSet(long newValue) {
103         while (true) {
104             long current = get();
105             if (compareAndSet(current, newValue))
106                 return current;
107         }
108     }
109
110     /**
111      * Atomically sets the value to the given updated value
112      * if the current value <tt>==</tt> the expected value.
113      *
114      * @param expect the expected value
115      * @param update the new value
116      * @return true if successful. False return indicates that
117      * the actual value was not equal to the expected value.
118      */
119     public final boolean compareAndSet(long expect, long update) {
120         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
121     }
122
123     /**
124      * Atomically sets the value to the given updated value
125      * if the current value <tt>==</tt> the expected value.
126      * May fail spuriously and does not provide ordering guarantees,
127      * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
128      *
129      * @param expect the expected value
130      * @param update the new value
131      * @return true if successful.
132      */
133     public final boolean weakCompareAndSet(long expect, long update) {
134         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
135     }
136
137     /**
138      * Atomically increments by one the current value.
139      *
140      * @return the previous value
141      */
142     public final long getAndIncrement() {
143         while (true) {
144             long current = get();
145             long next = current + 1;
146             if (compareAndSet(current, next))
147                 return current;
148         }
149     }
150
151     /**
152      * Atomically decrements by one the current value.
153      *
154      * @return the previous value
155      */
156     public final long getAndDecrement() {
157         while (true) {
158             long current = get();
159             long next = current - 1;
160             if (compareAndSet(current, next))
161                 return current;
162         }
163     }
164
165     /**
166      * Atomically adds the given value to the current value.
167      *
168      * @param delta the value to add
169      * @return the previous value
170      */
171     public final long getAndAdd(long delta) {
172         while (true) {
173             long current = get();
174             long next = current + delta;
175             if (compareAndSet(current, next))
176                 return current;
177         }
178     }
179
180     /**
181      * Atomically increments by one the current value.
182      *
183      * @return the updated value
184      */
185     public final long incrementAndGet() {
186         for (;;) {
187             long current = get();
188             long next = current + 1;
189             if (compareAndSet(current, next))
190                 return next;
191         }
192     }
193
194     /**
195      * Atomically decrements by one the current value.
196      *
197      * @return the updated value
198      */
199     public final long decrementAndGet() {
200         for (;;) {
201             long current = get();
202             long next = current - 1;
203             if (compareAndSet(current, next))
204                 return next;
205         }
206     }
207
208     /**
209      * Atomically adds the given value to the current value.
210      *
211      * @param delta the value to add
212      * @return the updated value
213      */
214     public final long addAndGet(long delta) {
215         for (;;) {
216             long current = get();
217             long next = current + delta;
218             if (compareAndSet(current, next))
219                 return next;
220         }
221     }
222
223     /**
224      * Returns the String representation of the current value.
225      * @return the String representation of the current value.
226      */
227     public String toString() {
228         return Long.toString(get());
229     }
230
231
232     public int intValue() {
233         return (int)get();
234     }
235
236     public long longValue() {
237         return (long)get();
238     }
239
240     public float floatValue() {
241         return (float)get();
242     }
243
244     public double doubleValue() {
245         return (double)get();
246     }
247
248 }