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

https://gitlab.com/essere.lab.public/qualitas.class-corpus · Java · 318 lines · 140 code · 28 blank · 150 comment · 52 complexity · d7b39c4771de4c7fa550286715fb3104 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 int} 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 AtomicIntegerFieldUpdater<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 integer 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> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
  43. return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
  44. }
  45. /**
  46. * Protected do-nothing constructor for use by subclasses.
  47. */
  48. protected AtomicIntegerFieldUpdater() {
  49. }
  50. /**
  51. * Atomically sets the field of the given object managed by this updater
  52. * to the given updated value if the current value {@code ==} the
  53. * expected value. This method is guaranteed to be atomic with respect to
  54. * other calls to {@code compareAndSet} and {@code set}, but not
  55. * necessarily with respect to other changes in the field.
  56. *
  57. * @param obj An object whose field to conditionally set
  58. * @param expect the expected value
  59. * @param update the new value
  60. * @return true if successful
  61. * @throws ClassCastException if {@code obj} is not an instance
  62. * of the class possessing the field established in the constructor
  63. */
  64. public abstract boolean compareAndSet(T obj, int expect, int update);
  65. /**
  66. * Atomically sets the field of the given object managed by this updater
  67. * to the given updated value if the current value {@code ==} the
  68. * expected value. This method is guaranteed to be atomic with respect to
  69. * other calls to {@code compareAndSet} and {@code set}, but not
  70. * necessarily with respect to other changes in the field.
  71. *
  72. * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
  73. * and does not provide ordering guarantees, so is only rarely an
  74. * appropriate alternative to {@code compareAndSet}.
  75. *
  76. * @param obj An object whose field to conditionally set
  77. * @param expect the expected value
  78. * @param update the new value
  79. * @return true if successful
  80. * @throws ClassCastException if {@code obj} is not an instance
  81. * of the class possessing the field established in the constructor
  82. */
  83. public abstract boolean weakCompareAndSet(T obj, int expect, int update);
  84. /**
  85. * Sets the field of the given object managed by this updater to the
  86. * given updated value. This operation is guaranteed to act as a volatile
  87. * store with respect to subsequent invocations of {@code compareAndSet}.
  88. *
  89. * @param obj An object whose field to set
  90. * @param newValue the new value
  91. */
  92. public abstract void set(T obj, int newValue);
  93. /**
  94. * Eventually sets the field of the given object managed by this
  95. * updater to the given updated value.
  96. *
  97. * @param obj An object whose field to set
  98. * @param newValue the new value
  99. * @since 1.6
  100. */
  101. public abstract void lazySet(T obj, int newValue);
  102. /**
  103. * Gets the current value held in the field of the given object managed
  104. * by this updater.
  105. *
  106. * @param obj An object whose field to get
  107. * @return the current value
  108. */
  109. public abstract int get(T obj);
  110. /**
  111. * Atomically sets the field of the given object managed by this updater
  112. * to the given value and returns the old value.
  113. *
  114. * @param obj An object whose field to get and set
  115. * @param newValue the new value
  116. * @return the previous value
  117. */
  118. public int getAndSet(T obj, int newValue) {
  119. for (;;) {
  120. int current = get(obj);
  121. if (compareAndSet(obj, current, newValue))
  122. return current;
  123. }
  124. }
  125. /**
  126. * Atomically increments by one the current value of the field of the
  127. * given object managed by this updater.
  128. *
  129. * @param obj An object whose field to get and set
  130. * @return the previous value
  131. */
  132. public int getAndIncrement(T obj) {
  133. for (;;) {
  134. int current = get(obj);
  135. int next = current + 1;
  136. if (compareAndSet(obj, current, next))
  137. return current;
  138. }
  139. }
  140. /**
  141. * Atomically decrements by one the current value of the field of the
  142. * given object managed by this updater.
  143. *
  144. * @param obj An object whose field to get and set
  145. * @return the previous value
  146. */
  147. public int getAndDecrement(T obj) {
  148. for (;;) {
  149. int current = get(obj);
  150. int next = current - 1;
  151. if (compareAndSet(obj, current, next))
  152. return current;
  153. }
  154. }
  155. /**
  156. * Atomically adds the given value to the current value of the field of
  157. * the given object managed by this updater.
  158. *
  159. * @param obj An object whose field to get and set
  160. * @param delta the value to add
  161. * @return the previous value
  162. */
  163. public int getAndAdd(T obj, int delta) {
  164. for (;;) {
  165. int current = get(obj);
  166. int next = current + delta;
  167. if (compareAndSet(obj, current, next))
  168. return current;
  169. }
  170. }
  171. /**
  172. * Atomically increments by one the current value of the field of the
  173. * given object managed by this updater.
  174. *
  175. * @param obj An object whose field to get and set
  176. * @return the updated value
  177. */
  178. public int incrementAndGet(T obj) {
  179. for (;;) {
  180. int current = get(obj);
  181. int next = current + 1;
  182. if (compareAndSet(obj, current, next))
  183. return next;
  184. }
  185. }
  186. /**
  187. * Atomically decrements by one the current value of the field of the
  188. * given object managed by this updater.
  189. *
  190. * @param obj An object whose field to get and set
  191. * @return the updated value
  192. */
  193. public int decrementAndGet(T obj) {
  194. for (;;) {
  195. int current = get(obj);
  196. int next = current - 1;
  197. if (compareAndSet(obj, current, next))
  198. return next;
  199. }
  200. }
  201. /**
  202. * Atomically adds the given value to the current value of the field of
  203. * the given object managed by this updater.
  204. *
  205. * @param obj An object whose field to get and set
  206. * @param delta the value to add
  207. * @return the updated value
  208. */
  209. public int addAndGet(T obj, int delta) {
  210. for (;;) {
  211. int current = get(obj);
  212. int next = current + delta;
  213. if (compareAndSet(obj, current, next))
  214. return next;
  215. }
  216. }
  217. /**
  218. * Standard hotspot implementation using intrinsics
  219. */
  220. private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<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. AtomicIntegerFieldUpdaterImpl(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 != int.class)
  241. throw new IllegalArgumentException("Must be integer 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, int expect, int update) {
  256. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  257. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  258. }
  259. public boolean weakCompareAndSet(T obj, int expect, int update) {
  260. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  261. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  262. }
  263. public void set(T obj, int newValue) {
  264. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  265. unsafe.putIntVolatile(obj, offset, newValue);
  266. }
  267. public void lazySet(T obj, int newValue) {
  268. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  269. unsafe.putOrderedInt(obj, offset, newValue);
  270. }
  271. public final int get(T obj) {
  272. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  273. return unsafe.getIntVolatile(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. }