package org.kantega.revoc.registry; import sun.misc.Unsafe; import java.lang.reflect.Field; /** * */ public class UnsafeAtomicLongArray { private static final Unsafe unsafe; private static final int shift; private static final int base; private final long[] array; int faults = 0; private int tries; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = (Unsafe) theUnsafe.get(null); int scale = unsafe.arrayIndexScale(long[].class); if ((scale & (scale - 1)) != 0) throw new Error("data type scale not a power of two"); shift = 31 - Integer.numberOfLeadingZeros(scale); base = unsafe.arrayBaseOffset(long[].class); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public UnsafeAtomicLongArray(int length) { array = new long[length]; } public static long byteOffset(int i) { return ((long) i << shift) + base; } private long getRaw(long offset) { return unsafe.getLongVolatile(array, offset); } public void incrementOffset(int i) { add(i, 1); } public void add(int i, long amount) { //array[i]++; while (true) { long offset = byteOffset(i); long current = getRaw(offset); long next = current + amount; if (unsafe.compareAndSwapLong(array, offset, current, next)) return; } } public final void set(int i, long newValue) { unsafe.putLongVolatile(array, byteOffset(i), newValue); } public final int length() { return array.length; } public final long get(int i) { //return array[i]; return getRaw(byteOffset(i)); } }