/projects/jre-1.6.0/src/java/util/concurrent/atomic/AtomicLongFieldUpdater.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus · Java · 408 lines · 221 code · 40 blank · 147 comment · 81 complexity · 29d5de28e60320bea7fc94e5dfb52473 MD5 · raw file

  1. /*
  2. * %W% %E%
  3. *
  4. * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
  5. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent.atomic;
  8. import sun.misc.Unsafe;
  9. import java.lang.reflect.*;
  10. /**
  11. * A reflection-based utility that enables atomic updates to
  12. * designated {@code volatile long} fields of designated classes.
  13. * This class is designed for use in atomic data structures in which
  14. * several fields of the same node are independently subject to atomic
  15. * updates.
  16. *
  17. * <p>Note that the guarantees of the {@code compareAndSet}
  18. * method in this class are weaker than in other atomic classes.
  19. * Because this class cannot ensure that all uses of the field
  20. * are appropriate for purposes of atomic access, it can
  21. * guarantee atomicity only with respect to other invocations of
  22. * {@code compareAndSet} and {@code set} on the same updater.
  23. *
  24. * @since 1.5
  25. * @author Doug Lea
  26. * @param <T> The type of the object holding the updatable field
  27. */
  28. public abstract class AtomicLongFieldUpdater<T> {
  29. /**
  30. * Creates and returns an updater for objects with the given field.
  31. * The Class argument is needed to check that reflective types and
  32. * generic types match.
  33. *
  34. * @param tclass the class of the objects holding the field
  35. * @param fieldName the name of the field to be updated.
  36. * @return the updater
  37. * @throws IllegalArgumentException if the field is not a
  38. * volatile long type.
  39. * @throws RuntimeException with a nested reflection-based
  40. * exception if the class does not hold field or is the wrong type.
  41. */
  42. public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
  43. if (AtomicLong.VM_SUPPORTS_LONG_CAS)
  44. return new CASUpdater<U>(tclass, fieldName);
  45. else
  46. return new LockedUpdater<U>(tclass, fieldName);
  47. }
  48. /**
  49. * Protected do-nothing constructor for use by subclasses.
  50. */
  51. protected AtomicLongFieldUpdater() {
  52. }
  53. /**
  54. * Atomically sets the field of the given object managed by this updater
  55. * to the given updated value if the current value {@code ==} the
  56. * expected value. This method is guaranteed to be atomic with respect to
  57. * other calls to {@code compareAndSet} and {@code set}, but not
  58. * necessarily with respect to other changes in the field.
  59. *
  60. * @param obj An object whose field to conditionally set
  61. * @param expect the expected value
  62. * @param update the new value
  63. * @return true if successful.
  64. * @throws ClassCastException if {@code obj} is not an instance
  65. * of the class possessing the field established in the constructor.
  66. */
  67. public abstract boolean compareAndSet(T obj, long expect, long update);
  68. /**
  69. * Atomically sets the field of the given object managed by this updater
  70. * to the given updated value if the current value {@code ==} the
  71. * expected value. This method is guaranteed to be atomic with respect to
  72. * other calls to {@code compareAndSet} and {@code set}, but not
  73. * necessarily with respect to other changes in the field.
  74. *
  75. * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
  76. * and does not provide ordering guarantees, so is only rarely an
  77. * appropriate alternative to {@code compareAndSet}.
  78. *
  79. * @param obj An object whose field to conditionally set
  80. * @param expect the expected value
  81. * @param update the new value
  82. * @return true if successful.
  83. * @throws ClassCastException if {@code obj} is not an instance
  84. * of the class possessing the field established in the constructor.
  85. */
  86. public abstract boolean weakCompareAndSet(T obj, long expect, long update);
  87. /**
  88. * Sets the field of the given object managed by this updater to the
  89. * given updated value. This operation is guaranteed to act as a volatile
  90. * store with respect to subsequent invocations of {@code compareAndSet}.
  91. *
  92. * @param obj An object whose field to set
  93. * @param newValue the new value
  94. */
  95. public abstract void set(T obj, long newValue);
  96. /**
  97. * Eventually sets the field of the given object managed by this
  98. * updater to the given updated value.
  99. *
  100. * @param obj An object whose field to set
  101. * @param newValue the new value
  102. * @since 1.6
  103. */
  104. public abstract void lazySet(T obj, long newValue);
  105. /**
  106. * Gets the current value held in the field of the given object managed
  107. * by this updater.
  108. *
  109. * @param obj An object whose field to get
  110. * @return the current value
  111. */
  112. public abstract long get(T obj);
  113. /**
  114. * Atomically sets the field of the given object managed by this updater
  115. * to the given value and returns the old value.
  116. *
  117. * @param obj An object whose field to get and set
  118. * @param newValue the new value
  119. * @return the previous value
  120. */
  121. public long getAndSet(T obj, long newValue) {
  122. for (;;) {
  123. long current = get(obj);
  124. if (compareAndSet(obj, current, newValue))
  125. return current;
  126. }
  127. }
  128. /**
  129. * Atomically increments by one the current value of the field of the
  130. * given object managed by this updater.
  131. *
  132. * @param obj An object whose field to get and set
  133. * @return the previous value
  134. */
  135. public long getAndIncrement(T obj) {
  136. for (;;) {
  137. long current = get(obj);
  138. long next = current + 1;
  139. if (compareAndSet(obj, current, next))
  140. return current;
  141. }
  142. }
  143. /**
  144. * Atomically decrements by one the current value of the field of the
  145. * given object managed by this updater.
  146. *
  147. * @param obj An object whose field to get and set
  148. * @return the previous value
  149. */
  150. public long getAndDecrement(T obj) {
  151. for (;;) {
  152. long current = get(obj);
  153. long next = current - 1;
  154. if (compareAndSet(obj, current, next))
  155. return current;
  156. }
  157. }
  158. /**
  159. * Atomically adds the given value to the current value of the field of
  160. * the given object managed by this updater.
  161. *
  162. * @param obj An object whose field to get and set
  163. * @param delta the value to add
  164. * @return the previous value
  165. */
  166. public long getAndAdd(T obj, long delta) {
  167. for (;;) {
  168. long current = get(obj);
  169. long next = current + delta;
  170. if (compareAndSet(obj, current, next))
  171. return current;
  172. }
  173. }
  174. /**
  175. * Atomically increments by one the current value of the field of the
  176. * given object managed by this updater.
  177. *
  178. * @param obj An object whose field to get and set
  179. * @return the updated value
  180. */
  181. public long incrementAndGet(T obj) {
  182. for (;;) {
  183. long current = get(obj);
  184. long next = current + 1;
  185. if (compareAndSet(obj, current, next))
  186. return next;
  187. }
  188. }
  189. /**
  190. * Atomically decrements by one the current value of the field of the
  191. * given object managed by this updater.
  192. *
  193. * @param obj An object whose field to get and set
  194. * @return the updated value
  195. */
  196. public long decrementAndGet(T obj) {
  197. for (;;) {
  198. long current = get(obj);
  199. long next = current - 1;
  200. if (compareAndSet(obj, current, next))
  201. return next;
  202. }
  203. }
  204. /**
  205. * Atomically adds the given value to the current value of the field of
  206. * the given object managed by this updater.
  207. *
  208. * @param obj An object whose field to get and set
  209. * @param delta the value to add
  210. * @return the updated value
  211. */
  212. public long addAndGet(T obj, long delta) {
  213. for (;;) {
  214. long current = get(obj);
  215. long next = current + delta;
  216. if (compareAndSet(obj, current, next))
  217. return next;
  218. }
  219. }
  220. private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
  221. private static final Unsafe unsafe = Unsafe.getUnsafe();
  222. private final long offset;
  223. private final Class<T> tclass;
  224. private final Class cclass;
  225. CASUpdater(Class<T> tclass, String fieldName) {
  226. Field field = null;
  227. Class caller = null;
  228. int modifiers = 0;
  229. try {
  230. field = tclass.getDeclaredField(fieldName);
  231. caller = sun.reflect.Reflection.getCallerClass(3);
  232. modifiers = field.getModifiers();
  233. sun.reflect.misc.ReflectUtil.ensureMemberAccess(
  234. caller, tclass, null, modifiers);
  235. sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
  236. } catch(Exception ex) {
  237. throw new RuntimeException(ex);
  238. }
  239. Class fieldt = field.getType();
  240. if (fieldt != long.class)
  241. throw new IllegalArgumentException("Must be long type");
  242. if (!Modifier.isVolatile(modifiers))
  243. throw new IllegalArgumentException("Must be volatile type");
  244. this.cclass = (Modifier.isProtected(modifiers) &&
  245. caller != tclass) ? caller : null;
  246. this.tclass = tclass;
  247. offset = unsafe.objectFieldOffset(field);
  248. }
  249. private void fullCheck(T obj) {
  250. if (!tclass.isInstance(obj))
  251. throw new ClassCastException();
  252. if (cclass != null)
  253. ensureProtectedAccess(obj);
  254. }
  255. public boolean compareAndSet(T obj, long expect, long update) {
  256. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  257. return unsafe.compareAndSwapLong(obj, offset, expect, update);
  258. }
  259. public boolean weakCompareAndSet(T obj, long expect, long update) {
  260. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  261. return unsafe.compareAndSwapLong(obj, offset, expect, update);
  262. }
  263. public void set(T obj, long newValue) {
  264. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  265. unsafe.putLongVolatile(obj, offset, newValue);
  266. }
  267. public void lazySet(T obj, long newValue) {
  268. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  269. unsafe.putOrderedLong(obj, offset, newValue);
  270. }
  271. public long get(T obj) {
  272. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  273. return unsafe.getLongVolatile(obj, offset);
  274. }
  275. private void ensureProtectedAccess(T obj) {
  276. if (cclass.isInstance(obj)) {
  277. return;
  278. }
  279. throw new RuntimeException (
  280. new IllegalAccessException("Class " +
  281. cclass.getName() +
  282. " can not access a protected member of class " +
  283. tclass.getName() +
  284. " using an instance of " +
  285. obj.getClass().getName()
  286. )
  287. );
  288. }
  289. }
  290. private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
  291. private static final Unsafe unsafe = Unsafe.getUnsafe();
  292. private final long offset;
  293. private final Class<T> tclass;
  294. private final Class cclass;
  295. LockedUpdater(Class<T> tclass, String fieldName) {
  296. Field field = null;
  297. Class caller = null;
  298. int modifiers = 0;
  299. try {
  300. field = tclass.getDeclaredField(fieldName);
  301. caller = sun.reflect.Reflection.getCallerClass(3);
  302. modifiers = field.getModifiers();
  303. sun.reflect.misc.ReflectUtil.ensureMemberAccess(
  304. caller, tclass, null, modifiers);
  305. sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
  306. } catch(Exception ex) {
  307. throw new RuntimeException(ex);
  308. }
  309. Class fieldt = field.getType();
  310. if (fieldt != long.class)
  311. throw new IllegalArgumentException("Must be long type");
  312. if (!Modifier.isVolatile(modifiers))
  313. throw new IllegalArgumentException("Must be volatile type");
  314. this.cclass = (Modifier.isProtected(modifiers) &&
  315. caller != tclass) ? caller : null;
  316. this.tclass = tclass;
  317. offset = unsafe.objectFieldOffset(field);
  318. }
  319. private void fullCheck(T obj) {
  320. if (!tclass.isInstance(obj))
  321. throw new ClassCastException();
  322. if (cclass != null)
  323. ensureProtectedAccess(obj);
  324. }
  325. public boolean compareAndSet(T obj, long expect, long update) {
  326. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  327. synchronized(this) {
  328. long v = unsafe.getLong(obj, offset);
  329. if (v != expect)
  330. return false;
  331. unsafe.putLong(obj, offset, update);
  332. return true;
  333. }
  334. }
  335. public boolean weakCompareAndSet(T obj, long expect, long update) {
  336. return compareAndSet(obj, expect, update);
  337. }
  338. public void set(T obj, long newValue) {
  339. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  340. synchronized(this) {
  341. unsafe.putLong(obj, offset, newValue);
  342. }
  343. }
  344. public void lazySet(T obj, long newValue) {
  345. set(obj, newValue);
  346. }
  347. public long get(T obj) {
  348. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  349. synchronized(this) {
  350. return unsafe.getLong(obj, offset);
  351. }
  352. }
  353. private void ensureProtectedAccess(T obj) {
  354. if (cclass.isInstance(obj)) {
  355. return;
  356. }
  357. throw new RuntimeException (
  358. new IllegalAccessException("Class " +
  359. cclass.getName() +
  360. " can not access a protected member of class " +
  361. tclass.getName() +
  362. " using an instance of " +
  363. obj.getClass().getName()
  364. )
  365. );
  366. }
  367. }
  368. }