1. /*
  2. * @(#)AtomicLong.java 1.6 04/02/13
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent.atomic;
  8. import sun.misc.Unsafe;
  9. /**
  10. * A <tt>long</tt> value that may be updated atomically. See the
  11. * {@link java.util.concurrent.atomic} package specification for
  12. * description of the properties of atomic variables. An
  13. * <tt>AtomicLong</tt> is used in applications such as atomically
  14. * incremented sequence numbers, and cannot be used as a replacement
  15. * for a {@link java.lang.Long}. However, this class does extend
  16. * <tt>Number</tt> to allow uniform access by tools and utilities that
  17. * deal with numerically-based classes.
  18. *
  19. * @since 1.5
  20. * @author Doug Lea
  21. */
  22. public class AtomicLong extends Number implements java.io.Serializable {
  23. private static final long serialVersionUID = 1927816293512124184L;
  24. // setup to use Unsafe.compareAndSwapLong for updates
  25. private static final Unsafe unsafe = Unsafe.getUnsafe();
  26. private static final long valueOffset;
  27. /**
  28. * Record whether the underlying JVM supports lockless
  29. * CompareAndSet for longs. While the unsafe.CompareAndSetLong
  30. * method works in either case, some constructions should be
  31. * handled at Java level to avoid locking user-visible locks.
  32. */
  33. static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
  34. /**
  35. * Returns whether underlying JVM supports lockless CompareAndSet
  36. * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
  37. */
  38. private static native boolean VMSupportsCS8();
  39. static {
  40. try {
  41. valueOffset = unsafe.objectFieldOffset
  42. (AtomicLong.class.getDeclaredField("value"));
  43. } catch(Exception ex) { throw new Error(ex); }
  44. }
  45. private volatile long value;
  46. /**
  47. * Create a new AtomicLong with the given initial value.
  48. *
  49. * @param initialValue the initial value
  50. */
  51. public AtomicLong(long initialValue) {
  52. value = initialValue;
  53. }
  54. /**
  55. * Create a new AtomicLong with initial value <tt>0</tt>.
  56. */
  57. public AtomicLong() {
  58. }
  59. /**
  60. * Get the current value.
  61. *
  62. * @return the current value
  63. */
  64. public final long get() {
  65. return value;
  66. }
  67. /**
  68. * Set to the given value.
  69. *
  70. * @param newValue the new value
  71. */
  72. public final void set(long newValue) {
  73. value = newValue;
  74. }
  75. /**
  76. * Set to the give value and return the old value.
  77. *
  78. * @param newValue the new value
  79. * @return the previous value
  80. */
  81. public final long getAndSet(long newValue) {
  82. while (true) {
  83. long current = get();
  84. if (compareAndSet(current, newValue))
  85. return current;
  86. }
  87. }
  88. /**
  89. * Atomically set the value to the given updated value
  90. * if the current value <tt>==</tt> the expected value.
  91. * @param expect the expected value
  92. * @param update the new value
  93. * @return true if successful. False return indicates that
  94. * the actual value was not equal to the expected value.
  95. */
  96. public final boolean compareAndSet(long expect, long update) {
  97. return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
  98. }
  99. /**
  100. * Atomically set the value to the given updated value
  101. * if the current value <tt>==</tt> the expected value.
  102. * May fail spuriously.
  103. * @param expect the expected value
  104. * @param update the new value
  105. * @return true if successful.
  106. */
  107. public final boolean weakCompareAndSet(long expect, long update) {
  108. return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
  109. }
  110. /**
  111. * Atomically increment by one the current value.
  112. * @return the previous value
  113. */
  114. public final long getAndIncrement() {
  115. while (true) {
  116. long current = get();
  117. long next = current + 1;
  118. if (compareAndSet(current, next))
  119. return current;
  120. }
  121. }
  122. /**
  123. * Atomically decrement by one the current value.
  124. * @return the previous value
  125. */
  126. public final long getAndDecrement() {
  127. while (true) {
  128. long current = get();
  129. long next = current - 1;
  130. if (compareAndSet(current, next))
  131. return current;
  132. }
  133. }
  134. /**
  135. * Atomically add the given value to current value.
  136. * @param delta the value to add
  137. * @return the previous value
  138. */
  139. public final long getAndAdd(long delta) {
  140. while (true) {
  141. long current = get();
  142. long next = current + delta;
  143. if (compareAndSet(current, next))
  144. return current;
  145. }
  146. }
  147. /**
  148. * Atomically increment by one the current value.
  149. * @return the updated value
  150. */
  151. public final long incrementAndGet() {
  152. for (;;) {
  153. long current = get();
  154. long next = current + 1;
  155. if (compareAndSet(current, next))
  156. return next;
  157. }
  158. }
  159. /**
  160. * Atomically decrement by one the current value.
  161. * @return the updated value
  162. */
  163. public final long decrementAndGet() {
  164. for (;;) {
  165. long current = get();
  166. long next = current - 1;
  167. if (compareAndSet(current, next))
  168. return next;
  169. }
  170. }
  171. /**
  172. * Atomically add the given value to current value.
  173. * @param delta the value to add
  174. * @return the updated value
  175. */
  176. public final long addAndGet(long delta) {
  177. for (;;) {
  178. long current = get();
  179. long next = current + delta;
  180. if (compareAndSet(current, next))
  181. return next;
  182. }
  183. }
  184. /**
  185. * Returns the String representation of the current value.
  186. * @return the String representation of the current value.
  187. */
  188. public String toString() {
  189. return Long.toString(get());
  190. }
  191. public int intValue() {
  192. return (int)get();
  193. }
  194. public long longValue() {
  195. return (long)get();
  196. }
  197. public float floatValue() {
  198. return (float)get();
  199. }
  200. public double doubleValue() {
  201. return (double)get();
  202. }
  203. }