14 package com.cliffc.aa.util;
16 import java.io.IOException;
17 import java.io.Serializable;
19 import java.util.concurrent.ConcurrentMap;
20 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
21 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
91 implements ConcurrentMap<Long,TypeV>,
Cloneable, Serializable {
98 private static final int _Obase = UNSAFE.arrayBaseOffset(Object[].
class);
99 private static final int _Oscale = UNSAFE.arrayIndexScale(Object[].
class);
100 private static long rawIndex(
final Object[] ary,
final int idx) {
101 assert idx >= 0 && idx < ary.length;
106 private static final int _Lbase = UNSAFE.arrayBaseOffset(
long[].
class);
107 private static final int _Lscale = UNSAFE.arrayIndexScale(
long[].
class);
108 private static long rawIndex(
final long[] ary,
final int idx) {
109 assert idx >= 0 && idx < ary.length;
119 private final boolean CAS(
final long offset,
final Object old,
final Object nnn ) {
120 return UNSAFE.compareAndSwapObject(
this, offset, old, nnn );
172 System.out.println(
"=========");
175 System.out.println(
"=========");
177 private static void print_impl(
final int i,
final long K,
final Object V) {
178 String p = (V instanceof Prime) ?
"prime_" :
"";
179 Object V2 = Prime.unbox(V);
180 String VS = (V2 ==
TOMBSTONE) ?
"tombstone" : V2.toString();
181 System.out.println(
"["+i+
"]=("+K+
","+p+VS+
")");
185 System.out.println(
"=========");
188 System.out.println(
"=========");
190 private static void print2_impl(
final int i,
final long K,
final Object V) {
191 if( V !=
null && Prime.unbox(V) !=
TOMBSTONE )
243 if( initial_sz < 0 )
throw new IllegalArgumentException(
"initial_sz argument must be >= 0");
258 public boolean containsKey(
long key ) {
return get(key) !=
null; }
307 public boolean replace (
long key, TypeV oldValue, TypeV newValue ) {
308 return putIfMatch( key, newValue, oldValue ) == oldValue;
311 @SuppressWarnings(
"unchecked")
312 private TypeV
putIfMatch(
long key, Object newVal, Object oldVal ) {
313 if (oldVal ==
null || newVal ==
null)
throw new NullPointerException();
319 oldVal.equals(curVal) ) {
323 return curVal ==
TOMBSTONE ? null : (TypeV)curVal;
326 assert !(res instanceof Prime);
328 return res ==
TOMBSTONE ? null : (TypeV)res;
350 if( val ==
null )
return false;
351 if( val ==
_val_1 )
return true;
353 if( V == val || V.equals(val) )
367 @SuppressWarnings(
"unchecked")
368 public final TypeV
get(
long key ) {
374 assert !(V instanceof Prime);
380 public TypeV
get ( Object key ) {
return (key instanceof Long) ?
get (((Long)key).longValue()) :
null; }
382 public TypeV
remove ( Object key ) {
return (key instanceof Long) ?
remove (((Long)key).longValue()) :
null; }
384 public boolean remove ( Object key, Object Val ) {
return (key instanceof Long) &&
remove(((Long) key).longValue(), Val); }
390 public TypeV
replace( Long key, TypeV Val ) {
return replace(key.longValue(), Val); }
392 public TypeV
put ( Long key, TypeV val ) {
return put(key.longValue(),val); }
394 public boolean replace( Long key, TypeV oldValue, TypeV newValue ) {
395 return replace(key.longValue(), oldValue, newValue);
408 if( topchm._newchm ==
null )
return;
416 private static final int hash(
long h) {
417 h ^= (h>>>20) ^ (h>>>12);
418 h ^= (h>>> 7) ^ (h>>> 4);
426 private static final class CHM implements Serializable {
456 AtomicReferenceFieldUpdater.newUpdater(
CHM.class,
CHM.class,
"_newchm");
475 AtomicLongFieldUpdater.newUpdater(
CHM.class,
"_resizers");
479 private boolean CAS_key(
int idx,
long old,
long key ) {
482 private boolean CAS_val(
int idx, Object old, Object val ) {
494 _keys =
new long [1<<logsize];
495 _vals =
new Object[1<<logsize];
501 Arrays.fill(
_keys,0);
502 Arrays.fill(
_vals,
null);
507 for(
int i=0; i<
_keys.length; i++ ) {
513 if( newchm !=
null ) {
514 System.out.println(
"----");
521 for(
int i=0; i<
_keys.length; i++ ) {
527 if( newchm !=
null ) {
528 System.out.println(
"----");
537 final int len =
_keys.length;
538 int idx = (
hash & (len-1));
543 final long K =
_keys[idx];
544 final Object V =
_vals[idx];
545 if( K ==
NO_KEY )
return null;
550 if( !(V instanceof
Prime) ) {
555 @SuppressWarnings(
"unused")
final CHM newchm =
_newchm;
570 idx = (idx+1)&(len-1);
581 private Object
putIfMatch(
final long key,
final Object putval,
final Object expVal ) {
583 assert putval !=
null;
584 assert !(putval instanceof
Prime);
585 assert !(expVal instanceof
Prime);
586 final int len =
_keys.length;
587 int idx = (
hash & (len-1));
639 idx = (idx+1)&(len-1);
648 if( putval == V )
return V;
653 if( (V ==
null &&
tableFull(reprobe_cnt,len)) ||
656 V instanceof
Prime) {
674 (expVal ==
null || !expVal.equals(V)) )
678 if(
CAS_val(idx, V, putval ) )
break;
695 if( V instanceof
Prime )
707 if( expVal !=
null ) {
714 return (V==
null && expVal!=
null) ?
TOMBSTONE : V;
748 int oldlen =
_keys.length;
756 if( sz >= (oldlen>>1) )
759 if( sz >= (oldlen>>2) ) {
761 if( sz >= (oldlen>>1) )
772 long tm = System.currentTimeMillis();
773 if( newsz <= oldlen &&
779 if( newsz < oldlen ) newsz = oldlen;
784 long len = ((1L << log2) << 1) + 2;
789 len = (1L << log2) + 2;
790 if (sz > ((len >> 2) + (len >> 1)))
throw new RuntimeException(
"Table is full.");
802 long megs = ((((1L<<log2)<<1)+8)<<3)>>20;
803 if( r >= 2 && megs > 0 ) {
812 try { Thread.sleep(megs); }
catch( Exception e ) { }
848 AtomicLongFieldUpdater.newUpdater(
CHM.class,
"_copyIdx");
855 AtomicLongFieldUpdater.newUpdater(
CHM.class,
"_copyDone");
863 assert newchm !=
null;
864 int oldlen =
_keys.length;
865 final int MIN_COPY_WORK = Math.min(oldlen,1024);
868 int panic_start = -1;
881 if( panic_start == -1 ) {
883 while( copyidx < (oldlen<<1) &&
886 if( !(copyidx < (oldlen<<1)) )
887 panic_start = copyidx;
892 for(
int i=0; i<MIN_COPY_WORK; i++ )
901 copyidx += MIN_COPY_WORK;
904 if( !copy_all && panic_start == -1 )
937 int oldlen =
_keys.length;
940 long nowDone = copyDone+workdone;
941 assert nowDone <= oldlen;
945 nowDone = copyDone+workdone;
946 assert nowDone <= oldlen;
953 if( nowDone == oldlen &&
984 Object oldval =
_vals[idx];
985 while( !(oldval instanceof
Prime) ) {
987 if(
CAS_val(idx,oldval,box) ) {
1000 oldval =
_vals[idx];
1009 Object old_unboxed = ((
Prime)oldval)._V;
1019 oldval =
_vals[idx];
1021 return copied_into_new;
1061 if(
_idx != -1 &&
_nextV ==
null )
throw new NoSuchElementException();
1082 if(
_prevV ==
null )
throw new IllegalStateException();
1088 public void remove() {
1119 return new AbstractCollection<TypeV>() {
1123 public Iterator<TypeV> iterator() {
return new SnapshotV(); }
1169 return new AbstractSet<Long> () {
1174 public IteratorLong iterator() {
return new IteratorLong(); }
1179 @SuppressWarnings(
"unchecked")
1181 long[] dom =
new long[
size()];
1182 IteratorLong i=(IteratorLong)
keySet().iterator();
1184 while( j < dom.length && i.hasNext() )
1185 dom[j++] = i.nextLong();
1195 if (val ==
null)
throw new NullPointerException();
1200 private class SnapshotE implements Iterator<Map.Entry<Long,TypeV>> {
1203 public void remove() {
1236 return new AbstractSet<Map.Entry<Long,TypeV>>() {
1239 public boolean remove(
final Object o ) {
1240 if (!(o instanceof Map.Entry))
return false;
1241 final Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1244 public boolean contains(
final Object o) {
1245 if (!(o instanceof Map.Entry))
return false;
1246 final Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1247 TypeV v =
get(e.getKey());
1248 return v !=
null && v.equals(e.getValue());
1250 public Iterator<Map.Entry<Long,TypeV>> iterator() {
return new SnapshotE(); }
1256 private void writeObject(java.io.ObjectOutputStream s)
throws IOException {
1257 s.defaultWriteObject();
1258 for(
long K :
keySet() ) {
1259 final Object V =
get(K);
1264 s.writeObject(
null);
1269 @SuppressWarnings(
"unchecked")
1270 private
void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
1271 s.defaultReadObject();
1274 final long K = s.readLong();
1275 final TypeV V = (TypeV) s.readObject();
1276 if( K ==
NO_KEY && V ==
null )
break;
1288 @SuppressWarnings(
"unchecked")
1305 }
catch (CloneNotSupportedException e) {
1307 throw new InternalError();