1 7 8 package java.util.concurrent.atomic; 9 import sun.misc.Unsafe; 10 import java.lang.reflect.*; 11 12 30 public abstract class AtomicLongFieldUpdater<T> { 31 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 71 public abstract boolean compareAndSet(T obj, long expect, long update); 72 73 87 88 public abstract boolean weakCompareAndSet(T obj, long expect, long update); 89 90 97 public abstract void set(T obj, long newValue); 98 99 104 public abstract long get(T obj); 105 106 113 public long getAndSet(T obj, long newValue) { 114 for (;;) { 115 long current = get(obj); 116 if (compareAndSet(obj, current, newValue)) 117 return current; 118 } 119 } 120 121 126 public long getAndIncrement(T obj) { 127 for (;;) { 128 long current = get(obj); 129 long next = current + 1; 130 if (compareAndSet(obj, current, next)) 131 return current; 132 } 133 } 134 135 136 141 public long getAndDecrement(T obj) { 142 for (;;) { 143 long current = get(obj); 144 long next = current - 1; 145 if (compareAndSet(obj, current, next)) 146 return current; 147 } 148 } 149 150 151 157 public long getAndAdd(T obj, long delta) { 158 for (;;) { 159 long current = get(obj); 160 long next = current + delta; 161 if (compareAndSet(obj, current, next)) 162 return current; 163 } 164 } 165 166 171 public long incrementAndGet(T obj) { 172 for (;;) { 173 long current = get(obj); 174 long next = current + 1; 175 if (compareAndSet(obj, current, next)) 176 return next; 177 } 178 } 179 180 181 186 public long decrementAndGet(T obj) { 187 for (;;) { 188 long current = get(obj); 189 long next = current - 1; 190 if (compareAndSet(obj, current, next)) 191 return next; 192 } 193 } 194 195 196 202 public long addAndGet(T obj, long delta) { 203 for (;;) { 204 long current = get(obj); 205 long next = current + delta; 206 if (compareAndSet(obj, current, next)) 207 return next; 208 } 209 } 210 211 private static class CASUpdater<T> extends AtomicLongFieldUpdater <T> { 212 private static final Unsafe unsafe = Unsafe.getUnsafe(); 213 private final long offset; 214 private final Class <T> tclass; 215 private final Class cclass; 216 217 CASUpdater(Class <T> tclass, String fieldName) { 218 Field field = null; 219 Class caller = null; 220 int modifiers = 0; 221 try { 222 field = tclass.getDeclaredField(fieldName); 223 caller = sun.reflect.Reflection.getCallerClass(3); 224 modifiers = field.getModifiers(); 225 sun.reflect.misc.ReflectUtil.ensureMemberAccess( 226 caller, tclass, null, modifiers); 227 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 228 } catch(Exception ex) { 229 throw new RuntimeException (ex); 230 } 231 232 Class fieldt = field.getType(); 233 if (fieldt != long.class) 234 throw new IllegalArgumentException ("Must be long type"); 235 236 if (!Modifier.isVolatile(modifiers)) 237 throw new IllegalArgumentException ("Must be volatile type"); 238 239 this.cclass = (Modifier.isProtected(modifiers) && 240 caller != tclass) ? caller : null; 241 this.tclass = tclass; 242 offset = unsafe.objectFieldOffset(field); 243 } 244 245 public boolean compareAndSet(T obj, long expect, long update) { 246 if (!tclass.isInstance(obj)) 247 throw new ClassCastException (); 248 if (cclass != null) 249 ensureProtectedAccess(obj); 250 return unsafe.compareAndSwapLong(obj, offset, expect, update); 251 } 252 253 public boolean weakCompareAndSet(T obj, long expect, long update) { 254 if (!tclass.isInstance(obj)) 255 throw new ClassCastException (); 256 if (cclass != null) 257 ensureProtectedAccess(obj); 258 return unsafe.compareAndSwapLong(obj, offset, expect, update); 259 } 260 261 public void set(T obj, long newValue) { 262 if (!tclass.isInstance(obj)) 263 throw new ClassCastException (); 264 if (cclass != null) 265 ensureProtectedAccess(obj); 266 unsafe.putLongVolatile(obj, offset, newValue); 267 } 268 269 public long get(T obj) { 270 if (!tclass.isInstance(obj)) 271 throw new ClassCastException (); 272 if (cclass != null) 273 ensureProtectedAccess(obj); 274 return unsafe.getLongVolatile(obj, offset); 275 } 276 277 private void ensureProtectedAccess(T obj) { 278 if (cclass.isInstance(obj)) { 279 return; 280 } 281 throw new RuntimeException ( 282 new IllegalAccessException ("Class " + 283 cclass.getName() + 284 " can not access a protected member of class " + 285 tclass.getName() + 286 " using an instance of " + 287 obj.getClass().getName() 288 ) 289 ); 290 } 291 } 292 293 294 private static class LockedUpdater<T> extends AtomicLongFieldUpdater <T> { 295 private static final Unsafe unsafe = Unsafe.getUnsafe(); 296 private final long offset; 297 private final Class <T> tclass; 298 private final Class cclass; 299 300 LockedUpdater(Class <T> tclass, String fieldName) { 301 Field field = null; 302 Class caller = null; 303 int modifiers = 0; 304 try { 305 field = tclass.getDeclaredField(fieldName); 306 caller = sun.reflect.Reflection.getCallerClass(3); 307 modifiers = field.getModifiers(); 308 sun.reflect.misc.ReflectUtil.ensureMemberAccess( 309 caller, tclass, null, modifiers); 310 sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); 311 } catch(Exception ex) { 312 throw new RuntimeException (ex); 313 } 314 315 Class fieldt = field.getType(); 316 if (fieldt != long.class) 317 throw new IllegalArgumentException ("Must be long type"); 318 319 if (!Modifier.isVolatile(modifiers)) 320 throw new IllegalArgumentException ("Must be volatile type"); 321 322 this.cclass = (Modifier.isProtected(modifiers) && 323 caller != tclass) ? caller : null; 324 this.tclass = tclass; 325 offset = unsafe.objectFieldOffset(field); 326 } 327 328 public boolean compareAndSet(T obj, long expect, long update) { 329 if (!tclass.isInstance(obj)) 330 throw new ClassCastException (); 331 if (cclass != null) 332 ensureProtectedAccess(obj); 333 synchronized(this) { 334 long v = unsafe.getLong(obj, offset); 335 if (v != expect) 336 return false; 337 unsafe.putLong(obj, offset, update); 338 return true; 339 } 340 } 341 342 public boolean weakCompareAndSet(T obj, long expect, long update) { 343 return compareAndSet(obj, expect, update); 344 } 345 346 public void set(T obj, long newValue) { 347 if (!tclass.isInstance(obj)) 348 throw new ClassCastException (); 349 if (cclass != null) 350 ensureProtectedAccess(obj); 351 synchronized(this) { 352 unsafe.putLong(obj, offset, newValue); 353 } 354 } 355 356 public long get(T obj) { 357 if (!tclass.isInstance(obj)) 358 throw new ClassCastException (); 359 if (cclass != null) 360 ensureProtectedAccess(obj); 361 synchronized(this) { 362 return unsafe.getLong(obj, offset); 363 } 364 } 365 366 private void ensureProtectedAccess(T obj) { 367 if (cclass.isInstance(obj)) { 368 return; 369 } 370 throw new RuntimeException ( 371 new IllegalAccessException ("Class " + 372 cclass.getName() + 373 " can not access a protected member of class " + 374 tclass.getName() + 375 " using an instance of " + 376 obj.getClass().getName() 377 ) 378 ); 379 } 380 } 381 } 382 383 | Popular Tags |