1:
6:
7: package ;
8: import ;
9: import ;
10:
11:
29: public abstract class AtomicLongFieldUpdater<T> {
30:
43: public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
44: if (AtomicLong.VM_SUPPORTS_LONG_CAS)
45: return new CASUpdater<U>(tclass, fieldName);
46: else
47: return new LockedUpdater<U>(tclass, fieldName);
48: }
49:
50:
53: protected AtomicLongFieldUpdater() {
54: }
55:
56:
70: public abstract boolean compareAndSet(T obj, long expect, long update);
71:
72:
88: public abstract boolean weakCompareAndSet(T obj, long expect, long update);
89:
90:
99: public abstract void set(T obj, long newValue);
100:
101:
109: public abstract void lazySet(T obj, long newValue);
110:
111:
118: public abstract long get(T obj);
119:
120:
128: public long getAndSet(T obj, long newValue) {
129: for (;;) {
130: long current = get(obj);
131: if (compareAndSet(obj, current, newValue))
132: return current;
133: }
134: }
135:
136:
143: public long getAndIncrement(T obj) {
144: for (;;) {
145: long current = get(obj);
146: long next = current + 1;
147: if (compareAndSet(obj, current, next))
148: return current;
149: }
150: }
151:
152:
159: public long getAndDecrement(T obj) {
160: for (;;) {
161: long current = get(obj);
162: long next = current - 1;
163: if (compareAndSet(obj, current, next))
164: return current;
165: }
166: }
167:
168:
176: public long getAndAdd(T obj, long delta) {
177: for (;;) {
178: long current = get(obj);
179: long next = current + delta;
180: if (compareAndSet(obj, current, next))
181: return current;
182: }
183: }
184:
185:
192: public long incrementAndGet(T obj) {
193: for (;;) {
194: long current = get(obj);
195: long next = current + 1;
196: if (compareAndSet(obj, current, next))
197: return next;
198: }
199: }
200:
201:
208: public long decrementAndGet(T obj) {
209: for (;;) {
210: long current = get(obj);
211: long next = current - 1;
212: if (compareAndSet(obj, current, next))
213: return next;
214: }
215: }
216:
217:
225: public long addAndGet(T obj, long delta) {
226: for (;;) {
227: long current = get(obj);
228: long next = current + delta;
229: if (compareAndSet(obj, current, next))
230: return next;
231: }
232: }
233:
234: private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
235: private static final Unsafe unsafe = Unsafe.getUnsafe();
236: private final long offset;
237: private final Class<T> tclass;
238: private final Class cclass;
239:
240: CASUpdater(Class<T> tclass, String fieldName) {
241: Field field = null;
242: Class caller = null;
243: int modifiers = 0;
244: try {
245: field = tclass.getDeclaredField(fieldName);
246: caller = sun.reflect.Reflection.getCallerClass(3);
247: modifiers = field.getModifiers();
248: sun.reflect.misc.ReflectUtil.ensureMemberAccess(
249: caller, tclass, null, modifiers);
250: sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
251: } catch(Exception ex) {
252: throw new RuntimeException(ex);
253: }
254:
255: Class fieldt = field.getType();
256: if (fieldt != long.class)
257: throw new IllegalArgumentException("Must be long type");
258:
259: if (!Modifier.isVolatile(modifiers))
260: throw new IllegalArgumentException("Must be volatile type");
261:
262: this.cclass = (Modifier.isProtected(modifiers) &&
263: caller != tclass) ? caller : null;
264: this.tclass = tclass;
265: offset = unsafe.objectFieldOffset(field);
266: }
267:
268: private void fullCheck(T obj) {
269: if (!tclass.isInstance(obj))
270: throw new ClassCastException();
271: if (cclass != null)
272: ensureProtectedAccess(obj);
273: }
274:
275: public boolean compareAndSet(T obj, long expect, long update) {
276: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
277: return unsafe.compareAndSwapLong(obj, offset, expect, update);
278: }
279:
280: public boolean weakCompareAndSet(T obj, long expect, long update) {
281: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
282: return unsafe.compareAndSwapLong(obj, offset, expect, update);
283: }
284:
285: public void set(T obj, long newValue) {
286: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
287: unsafe.putLongVolatile(obj, offset, newValue);
288: }
289:
290: public void lazySet(T obj, long newValue) {
291: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
292: unsafe.putOrderedLong(obj, offset, newValue);
293: }
294:
295: public long get(T obj) {
296: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
297: return unsafe.getLongVolatile(obj, offset);
298: }
299:
300: private void ensureProtectedAccess(T obj) {
301: if (cclass.isInstance(obj)) {
302: return;
303: }
304: throw new RuntimeException (
305: new IllegalAccessException("Class " +
306: cclass.getName() +
307: " can not access a protected member of class " +
308: tclass.getName() +
309: " using an instance of " +
310: obj.getClass().getName()
311: )
312: );
313: }
314: }
315:
316:
317: private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
318: private static final Unsafe unsafe = Unsafe.getUnsafe();
319: private final long offset;
320: private final Class<T> tclass;
321: private final Class cclass;
322:
323: LockedUpdater(Class<T> tclass, String fieldName) {
324: Field field = null;
325: Class caller = null;
326: int modifiers = 0;
327: try {
328: field = tclass.getDeclaredField(fieldName);
329: caller = sun.reflect.Reflection.getCallerClass(3);
330: modifiers = field.getModifiers();
331: sun.reflect.misc.ReflectUtil.ensureMemberAccess(
332: caller, tclass, null, modifiers);
333: sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
334: } catch(Exception ex) {
335: throw new RuntimeException(ex);
336: }
337:
338: Class fieldt = field.getType();
339: if (fieldt != long.class)
340: throw new IllegalArgumentException("Must be long type");
341:
342: if (!Modifier.isVolatile(modifiers))
343: throw new IllegalArgumentException("Must be volatile type");
344:
345: this.cclass = (Modifier.isProtected(modifiers) &&
346: caller != tclass) ? caller : null;
347: this.tclass = tclass;
348: offset = unsafe.objectFieldOffset(field);
349: }
350:
351: private void fullCheck(T obj) {
352: if (!tclass.isInstance(obj))
353: throw new ClassCastException();
354: if (cclass != null)
355: ensureProtectedAccess(obj);
356: }
357:
358: public boolean compareAndSet(T obj, long expect, long update) {
359: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
360: synchronized(this) {
361: long v = unsafe.getLong(obj, offset);
362: if (v != expect)
363: return false;
364: unsafe.putLong(obj, offset, update);
365: return true;
366: }
367: }
368:
369: public boolean weakCompareAndSet(T obj, long expect, long update) {
370: return compareAndSet(obj, expect, update);
371: }
372:
373: public void set(T obj, long newValue) {
374: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
375: synchronized(this) {
376: unsafe.putLong(obj, offset, newValue);
377: }
378: }
379:
380: public void lazySet(T obj, long newValue) {
381: set(obj, newValue);
382: }
383:
384: public long get(T obj) {
385: if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
386: synchronized(this) {
387: return unsafe.getLong(obj, offset);
388: }
389: }
390:
391: private void ensureProtectedAccess(T obj) {
392: if (cclass.isInstance(obj)) {
393: return;
394: }
395: throw new RuntimeException (
396: new IllegalAccessException("Class " +
397: cclass.getName() +
398: " can not access a protected member of class " +
399: tclass.getName() +
400: " using an instance of " +
401: obj.getClass().getName()
402: )
403: );
404: }
405: }
406: }