/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java

https://gitlab.com/lobl.pavel/gcc-6.2.0 · Java · 316 lines · 140 code · 28 blank · 148 comment · 52 complexity · 1801d6b780a0ad3c2aef1cf659dfe811 MD5 · raw file

  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. package java.util.concurrent.atomic;
  7. import sun.misc.Unsafe;
  8. import java.lang.reflect.*;
  9. /**
  10. * A reflection-based utility that enables atomic updates to
  11. * designated <tt>volatile int</tt> fields of designated classes.
  12. * This class is designed for use in atomic data structures in which
  13. * several fields of the same node are independently subject to atomic
  14. * updates.
  15. *
  16. * <p>Note that the guarantees of the {@code compareAndSet}
  17. * method in this class are weaker than in other atomic classes.
  18. * Because this class cannot ensure that all uses of the field
  19. * are appropriate for purposes of atomic access, it can
  20. * guarantee atomicity only with respect to other invocations of
  21. * {@code compareAndSet} and {@code set} on the same updater.
  22. *
  23. * @since 1.5
  24. * @author Doug Lea
  25. * @param <T> The type of the object holding the updatable field
  26. */
  27. public abstract class AtomicIntegerFieldUpdater<T> {
  28. /**
  29. * Creates and returns an updater for objects with the given field.
  30. * The Class argument is needed to check that reflective types and
  31. * generic types match.
  32. *
  33. * @param tclass the class of the objects holding the field
  34. * @param fieldName the name of the field to be updated
  35. * @return the updater
  36. * @throws IllegalArgumentException if the field is not a
  37. * volatile integer type
  38. * @throws RuntimeException with a nested reflection-based
  39. * exception if the class does not hold field or is the wrong type
  40. */
  41. public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
  42. return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
  43. }
  44. /**
  45. * Protected do-nothing constructor for use by subclasses.
  46. */
  47. protected AtomicIntegerFieldUpdater() {
  48. }
  49. /**
  50. * Atomically sets the field of the given object managed by this updater
  51. * to the given updated value if the current value <tt>==</tt> the
  52. * expected value. This method is guaranteed to be atomic with respect to
  53. * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
  54. * necessarily with respect to other changes in the field.
  55. *
  56. * @param obj An object whose field to conditionally set
  57. * @param expect the expected value
  58. * @param update the new value
  59. * @return true if successful
  60. * @throws ClassCastException if <tt>obj</tt> is not an instance
  61. * of the class possessing the field established in the constructor
  62. */
  63. public abstract boolean compareAndSet(T obj, int expect, int update);
  64. /**
  65. * Atomically sets the field of the given object managed by this updater
  66. * to the given updated value if the current value <tt>==</tt> the
  67. * expected value. This method is guaranteed to be atomic with respect to
  68. * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
  69. * necessarily with respect to other changes in the field.
  70. * May fail spuriously and does not provide ordering guarantees,
  71. * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
  72. *
  73. * @param obj An object whose field to conditionally set
  74. * @param expect the expected value
  75. * @param update the new value
  76. * @return true if successful
  77. * @throws ClassCastException if <tt>obj</tt> is not an instance
  78. * of the class possessing the field established in the constructor
  79. */
  80. public abstract boolean weakCompareAndSet(T obj, int expect, int update);
  81. /**
  82. * Sets the field of the given object managed by this updater to the
  83. * given updated value. This operation is guaranteed to act as a volatile
  84. * store with respect to subsequent invocations of
  85. * <tt>compareAndSet</tt>.
  86. *
  87. * @param obj An object whose field to set
  88. * @param newValue the new value
  89. */
  90. public abstract void set(T obj, int newValue);
  91. /**
  92. * Eventually sets the field of the given object managed by this
  93. * updater to the given updated value.
  94. *
  95. * @param obj An object whose field to set
  96. * @param newValue the new value
  97. * @since 1.6
  98. */
  99. public abstract void lazySet(T obj, int newValue);
  100. /**
  101. * Gets the current value held in the field of the given object managed
  102. * by this updater.
  103. *
  104. * @param obj An object whose field to get
  105. * @return the current value
  106. */
  107. public abstract int get(T obj);
  108. /**
  109. * Atomically sets the field of the given object managed by this updater
  110. * to the given value and returns the old value.
  111. *
  112. * @param obj An object whose field to get and set
  113. * @param newValue the new value
  114. * @return the previous value
  115. */
  116. public int getAndSet(T obj, int newValue) {
  117. for (;;) {
  118. int current = get(obj);
  119. if (compareAndSet(obj, current, newValue))
  120. return current;
  121. }
  122. }
  123. /**
  124. * Atomically increments by one the current value of the field of the
  125. * given object managed by this updater.
  126. *
  127. * @param obj An object whose field to get and set
  128. * @return the previous value
  129. */
  130. public int getAndIncrement(T obj) {
  131. for (;;) {
  132. int current = get(obj);
  133. int next = current + 1;
  134. if (compareAndSet(obj, current, next))
  135. return current;
  136. }
  137. }
  138. /**
  139. * Atomically decrements by one the current value of the field of the
  140. * given object managed by this updater.
  141. *
  142. * @param obj An object whose field to get and set
  143. * @return the previous value
  144. */
  145. public int getAndDecrement(T obj) {
  146. for (;;) {
  147. int current = get(obj);
  148. int next = current - 1;
  149. if (compareAndSet(obj, current, next))
  150. return current;
  151. }
  152. }
  153. /**
  154. * Atomically adds the given value to the current value of the field of
  155. * the given object managed by this updater.
  156. *
  157. * @param obj An object whose field to get and set
  158. * @param delta the value to add
  159. * @return the previous value
  160. */
  161. public int getAndAdd(T obj, int delta) {
  162. for (;;) {
  163. int current = get(obj);
  164. int next = current + delta;
  165. if (compareAndSet(obj, current, next))
  166. return current;
  167. }
  168. }
  169. /**
  170. * Atomically increments by one the current value of the field of the
  171. * given object managed by this updater.
  172. *
  173. * @param obj An object whose field to get and set
  174. * @return the updated value
  175. */
  176. public int incrementAndGet(T obj) {
  177. for (;;) {
  178. int current = get(obj);
  179. int next = current + 1;
  180. if (compareAndSet(obj, current, next))
  181. return next;
  182. }
  183. }
  184. /**
  185. * Atomically decrements by one the current value of the field of the
  186. * given object managed by this updater.
  187. *
  188. * @param obj An object whose field to get and set
  189. * @return the updated value
  190. */
  191. public int decrementAndGet(T obj) {
  192. for (;;) {
  193. int current = get(obj);
  194. int next = current - 1;
  195. if (compareAndSet(obj, current, next))
  196. return next;
  197. }
  198. }
  199. /**
  200. * Atomically adds the given value to the current value of the field of
  201. * the given object managed by this updater.
  202. *
  203. * @param obj An object whose field to get and set
  204. * @param delta the value to add
  205. * @return the updated value
  206. */
  207. public int addAndGet(T obj, int delta) {
  208. for (;;) {
  209. int current = get(obj);
  210. int next = current + delta;
  211. if (compareAndSet(obj, current, next))
  212. return next;
  213. }
  214. }
  215. /**
  216. * Standard hotspot implementation using intrinsics
  217. */
  218. private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
  219. private static final Unsafe unsafe = Unsafe.getUnsafe();
  220. private final long offset;
  221. private final Class<T> tclass;
  222. private final Class cclass;
  223. AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
  224. Field field = null;
  225. Class caller = null;
  226. int modifiers = 0;
  227. try {
  228. field = tclass.getDeclaredField(fieldName);
  229. caller = sun.reflect.Reflection.getCallerClass(3);
  230. modifiers = field.getModifiers();
  231. sun.reflect.misc.ReflectUtil.ensureMemberAccess(
  232. caller, tclass, null, modifiers);
  233. sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
  234. } catch(Exception ex) {
  235. throw new RuntimeException(ex);
  236. }
  237. Class fieldt = field.getType();
  238. if (fieldt != int.class)
  239. throw new IllegalArgumentException("Must be integer type");
  240. if (!Modifier.isVolatile(modifiers))
  241. throw new IllegalArgumentException("Must be volatile type");
  242. this.cclass = (Modifier.isProtected(modifiers) &&
  243. caller != tclass) ? caller : null;
  244. this.tclass = tclass;
  245. offset = unsafe.objectFieldOffset(field);
  246. }
  247. private void fullCheck(T obj) {
  248. if (!tclass.isInstance(obj))
  249. throw new ClassCastException();
  250. if (cclass != null)
  251. ensureProtectedAccess(obj);
  252. }
  253. public boolean compareAndSet(T obj, int expect, int update) {
  254. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  255. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  256. }
  257. public boolean weakCompareAndSet(T obj, int expect, int update) {
  258. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  259. return unsafe.compareAndSwapInt(obj, offset, expect, update);
  260. }
  261. public void set(T obj, int newValue) {
  262. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  263. unsafe.putIntVolatile(obj, offset, newValue);
  264. }
  265. public void lazySet(T obj, int newValue) {
  266. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  267. unsafe.putOrderedInt(obj, offset, newValue);
  268. }
  269. public final int get(T obj) {
  270. if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
  271. return unsafe.getIntVolatile(obj, offset);
  272. }
  273. private void ensureProtectedAccess(T obj) {
  274. if (cclass.isInstance(obj)) {
  275. return;
  276. }
  277. throw new RuntimeException(
  278. new IllegalAccessException("Class " +
  279. cclass.getName() +
  280. " can not access a protected member of class " +
  281. tclass.getName() +
  282. " using an instance of " +
  283. obj.getClass().getName()
  284. )
  285. );
  286. }
  287. }
  288. }