package org.jctools.maps.cat_test;
import java.lang.reflect.Field;
import sun.misc.Unsafe;

public final class UnsafeCounter extends Counter {
  public String name() { return "Unsafe"; }
  private static final Unsafe _unsafe = UtilUnsafe.getUnsafe();
  private static final long CNT_OFFSET;
  static { {			// <clinit>
    Field f = null;
    try { 
      f = UnsafeCounter.class.getDeclaredField("_cnt"); 
    } catch( java.lang.NoSuchFieldException e ) {
      throw new Error(e);
    } 
    CNT_OFFSET = _unsafe.objectFieldOffset(f);
    }
  }

  private long _cnt;
  public long get(){ return _cnt; }
  public void add( final long x ) { 
    long cnt=0;
    do { 
      cnt = _cnt;
    } while( !_unsafe.compareAndSwapLong(this,CNT_OFFSET,cnt,cnt+x) );
  }


  private static class UtilUnsafe {
    private UtilUnsafe() { } // dummy private constructor
    public static Unsafe getUnsafe() {
      // Not on bootclasspath
      if( UtilUnsafe.class.getClassLoader() == null )
        return Unsafe.getUnsafe();
      try {
        final Field fld = Unsafe.class.getDeclaredField("theUnsafe");
        fld.setAccessible(true);
        return (Unsafe) fld.get(UtilUnsafe.class);
      } catch (Exception e) {
        throw new RuntimeException("Could not obtain access to sun.misc.Unsafe", e);
      }
    }
  }

}
