/** Removes all of the mappings from this map. */ public void clear() { // Smack a new empty table down Object[] newkvs = new NonBlockingHashtable(MIN_SIZE)._kvs; while( !CAS_kvs(_kvs,newkvs) ) // Spin until the clear works ; }
private final Object[] help_copy( Object[] helper ) { // Read the top-level KVS only once. We'll try to help this copy along, // even if it gets promoted out from under us (i.e., the copy completes // and another KVS becomes the top-level copy). Object[] topkvs = _kvs; CHM topchm = chm(topkvs); if( topchm._newkvs == null ) return helper; // No copy in-progress topchm.help_copy_impl(this,topkvs,false); return helper; }
@Override public void clear ( ) { NonBlockingHashtable.this.clear ( ); } @Override public int size ( ) { return NonBlockingHashtable.this.size ( ); }
assert !(putval instanceof Prime); assert !(expVal instanceof Prime); final int fullhash = hash (key); // throws NullPointerException if key null final int len = len (kvs); // Count of key/value pairs, reads kvs.length final CHM chm = chm (kvs); // Reads kvs[0] final int[] hashes = hashes(kvs); // Reads kvs[1], read before kvs[0] int idx = fullhash & (len-1); Object[] newkvs=null; while( true ) { // Spin till we get a Key slot V = val(kvs,idx); // Get old value (before volatile read below!) K = key(kvs,idx); // Get current key if( K == null ) { // Slot is free? if( CAS_key(kvs,idx, null, key ) ) { // Claim slot for Key chm._slots.add(1); // Raise key-slots-used count K = key(kvs,idx); // CAS failed, get updated value assert K != null; // If keys[idx] is null, CAS shoulda worked if( keyeq(K,key,hashes,idx,fullhash) ) break; // Got it! if( ++reprobe_cnt >= reprobe_limit(len) || // too many probes or if( expVal != null ) topmap.help_copy(newkvs); // help along an existing copy return putIfMatch(topmap,newkvs,key,putval,expVal); return putIfMatch(topmap,chm.copy_slot_and_check(topmap,kvs,idx,expVal),key,putval,expVal);
private static final Object get_impl( final NonBlockingHashtable topmap, final Object[] kvs, final Object key, final int fullhash ) { final int len = len (kvs); // Count of key/value pairs, reads kvs.length final CHM chm = chm (kvs); // The CHM, for a volatile read below; reads slot 0 of kvs final int[] hashes=hashes(kvs); // The memoized hashes; reads slot 1 of kvs final Object K = key(kvs,idx); // Get key before volatile read, could be null final Object V = val(kvs,idx); // Get value before volatile read, could be null or Tombstone or Prime if( K == null ) return null; // A clear miss if( keyeq(K,key,hashes,idx,fullhash) ) { return get_impl(topmap,chm.copy_slot_and_check(topmap,kvs,idx,key),key,fullhash); // Retry in the new table if( ++reprobe_cnt >= reprobe_limit(len) || // too many probes return newkvs == null ? null : get_impl(topmap,topmap.help_copy(newkvs),key,fullhash); // Retry in the new table
private final void print2( Object[] kvs) { for( int i=0; i<len(kvs); i++ ) { Object key = key(kvs,i); Object val = val(kvs,i); Object U = Prime.unbox(val); if( key != null && key != TOMBSTONE && // key is sane val != null && U != TOMBSTONE ) { // val is sane String p = (val==U) ? "" : "prime_"; System.out.println(""+i+" ("+key+","+p+val+")"); } } Object[] newkvs = chm(kvs)._newkvs; // New table, if any if( newkvs != null ) { System.out.println("----"); print2(newkvs); } }
private final void print( Object[] kvs ) { for( int i=0; i<len(kvs); i++ ) { Object K = key(kvs,i); if( K != null ) { String KS = (K == TOMBSTONE) ? "XXX" : K.toString(); Object V = val(kvs,i); Object U = Prime.unbox(V); String p = (V==U) ? "" : "prime_"; String US = (U == TOMBSTONE) ? "tombstone" : U.toString(); System.out.println(""+i+" ("+KS+","+p+US+")"); } } Object[] newkvs = chm(kvs)._newkvs; // New table, if any if( newkvs != null ) { System.out.println("----"); print(newkvs); } } // print only the live values, broken down by the table they are in
/** * Creates a shallow copy of this hashtable. All the structure of the * hashtable itself is copied, but the keys and values are not cloned. * This is a relatively expensive operation. * * @return a clone of the hashtable. */ @Override public Object clone() { try { // Must clone, to get the class right; NBHM might have been // extended so it would be wrong to just make a new NBHM. NonBlockingHashtable<TypeK,TypeV> t = (NonBlockingHashtable<TypeK,TypeV>) super.clone(); // But I don't have an atomic clone operation - the underlying _kvs // structure is undergoing rapid change. If I just clone the _kvs // field, the CHM in _kvs[0] won't be in sync. // // Wipe out the cloned array (it was shallow anyways). t.clear(); // Now copy sanely for( TypeK K : keySet() ) { final TypeV V = get(K); // Do an official 'get' t.put(K,V); } return t; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); // Nothing to write for( Object K : keySet() ) { final Object V = get(K); // Do an official 'get' s.writeObject(K); // Write the <TypeK,TypeV> pair s.writeObject(V); } s.writeObject(null); // Sentinel to indicate end-of-data s.writeObject(null); }
/** Legacy method testing if some key maps into the specified value in this * table. This method is identical in functionality to {@link * #containsValue}, and exists solely to ensure full compatibility with * class {@link java.util.Hashtable}, which supported this method prior to * introduction of the Java Collections framework. * @param val a value to search for * @return <tt>true</tt> if this map maps one or more keys to the specified value * @throws NullPointerException if the specified value is null */ public boolean contains ( Object val ) { return containsValue(val); }
/** Tests if the key in the table using the <tt>equals</tt> method. * @return <tt>true</tt> if the key is in the table using the <tt>equals</tt> method * @throws NullPointerException if the specified key is null */ public boolean containsKey( Object key ) { return get(key) != null; }
@Override public boolean contains( Object k ) { return NonBlockingHashtable.this.containsKey(k); } @Override public boolean remove ( Object k ) { return NonBlockingHashtable.this.remove (k) != null; }
Iterator<Entry<TypeK,TypeV>> i = entrySet().iterator(); if( !i.hasNext()) return "{}";
assert !(putval instanceof Prime); assert !(expVal instanceof Prime); final int fullhash = hash (key); // throws NullPointerException if key null final int len = len (kvs); // Count of key/value pairs, reads kvs.length final CHM chm = chm (kvs); // Reads kvs[0] final int[] hashes = hashes(kvs); // Reads kvs[1], read before kvs[0] int idx = fullhash & (len-1); Object[] newkvs=null; while( true ) { // Spin till we get a Key slot V = val(kvs,idx); // Get old value (before volatile read below!) K = key(kvs,idx); // Get current key if( K == null ) { // Slot is free? if( CAS_key(kvs,idx, null, key ) ) { // Claim slot for Key chm._slots.add(1); // Raise key-slots-used count K = key(kvs,idx); // CAS failed, get updated value assert K != null; // If keys[idx] is null, CAS shoulda worked if( keyeq(K,key,hashes,idx,fullhash) ) break; // Got it! if( ++reprobe_cnt >= reprobe_limit(len) || // too many probes or if( expVal != null ) topmap.help_copy(newkvs); // help along an existing copy return putIfMatch(topmap,newkvs,key,putval,expVal); return putIfMatch(topmap,chm.copy_slot_and_check(topmap,kvs,idx,expVal),key,putval,expVal);
private static final Object get_impl( final NonBlockingHashtable topmap, final Object[] kvs, final Object key, final int fullhash ) { final int len = len (kvs); // Count of key/value pairs, reads kvs.length final CHM chm = chm (kvs); // The CHM, for a volatile read below; reads slot 0 of kvs final int[] hashes=hashes(kvs); // The memoized hashes; reads slot 1 of kvs final Object K = key(kvs,idx); // Get key before volatile read, could be null final Object V = val(kvs,idx); // Get value before volatile read, could be null or Tombstone or Prime if( K == null ) return null; // A clear miss if( keyeq(K,key,hashes,idx,fullhash) ) { return get_impl(topmap,chm.copy_slot_and_check(topmap,kvs,idx,key),key,fullhash); // Retry in the new table if( ++reprobe_cnt >= reprobe_limit(len) || // too many probes return newkvs == null ? null : get_impl(topmap,topmap.help_copy(newkvs),key,fullhash); // Retry in the new table
private final void print2( Object[] kvs) { for( int i=0; i<len(kvs); i++ ) { Object key = key(kvs,i); Object val = val(kvs,i); Object U = Prime.unbox(val); if( key != null && key != TOMBSTONE && // key is sane val != null && U != TOMBSTONE ) { // val is sane String p = (val==U) ? "" : "prime_"; System.out.println(""+i+" ("+key+","+p+val+")"); } } Object[] newkvs = chm(kvs)._newkvs; // New table, if any if( newkvs != null ) { System.out.println("----"); print2(newkvs); } }
private final void print( Object[] kvs ) { for( int i=0; i<len(kvs); i++ ) { Object K = key(kvs,i); if( K != null ) { String KS = (K == TOMBSTONE) ? "XXX" : K.toString(); Object V = val(kvs,i); Object U = Prime.unbox(V); String p = (V==U) ? "" : "prime_"; String US = (U == TOMBSTONE) ? "tombstone" : U.toString(); System.out.println(""+i+" ("+KS+","+p+US+")"); } } Object[] newkvs = chm(kvs)._newkvs; // New table, if any if( newkvs != null ) { System.out.println("----"); print(newkvs); } } // print only the live values, broken down by the table they are in
/** * Creates a shallow copy of this hashtable. All the structure of the * hashtable itself is copied, but the keys and values are not cloned. * This is a relatively expensive operation. * * @return a clone of the hashtable. */ @Override public Object clone() { try { // Must clone, to get the class right; NBHM might have been // extended so it would be wrong to just make a new NBHM. NonBlockingHashtable<TypeK,TypeV> t = (NonBlockingHashtable<TypeK,TypeV>) super.clone(); // But I don't have an atomic clone operation - the underlying _kvs // structure is undergoing rapid change. If I just clone the _kvs // field, the CHM in _kvs[0] won't be in sync. // // Wipe out the cloned array (it was shallow anyways). t.clear(); // Now copy sanely for( TypeK K : keySet() ) { final TypeV V = get(K); // Do an official 'get' t.put(K,V); } return t; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); // Nothing to write for( Object K : keySet() ) { final Object V = get(K); // Do an official 'get' s.writeObject(K); // Write the <TypeK,TypeV> pair s.writeObject(V); } s.writeObject(null); // Sentinel to indicate end-of-data s.writeObject(null); }
/** Legacy method testing if some key maps into the specified value in this * table. This method is identical in functionality to {@link * #containsValue}, and exists solely to ensure full compatibility with * class {@link java.util.Hashtable}, which supported this method prior to * introduction of the Java Collections framework. * @param val a value to search for * @return <tt>true</tt> if this map maps one or more keys to the specified value * @throws NullPointerException if the specified value is null */ public boolean contains ( Object val ) { return containsValue(val); }