aa
NonBlockingHashMapLong.java
Go to the documentation of this file.
1 /*
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 package com.cliffc.aa.util;
15 
16 import java.io.IOException;
17 import java.io.Serializable;
18 import java.util.*;
19 import java.util.concurrent.ConcurrentMap;
20 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
21 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
22 
23 import static com.cliffc.aa.util.UtilUnsafe.UNSAFE;
24 import static com.cliffc.aa.util.UtilUnsafe.fieldOffset;
25 
26 
89 public class NonBlockingHashMapLong<TypeV>
90  extends AbstractMap<Long,TypeV>
91  implements ConcurrentMap<Long,TypeV>, Cloneable, Serializable {
92 
93  private static final long serialVersionUID = 1234123412341234124L;
94 
95  private static final int REPROBE_LIMIT=10; // Too many reprobes then force a table-resize
96 
97  // --- Bits to allow Unsafe access to arrays
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;
102  // Note the long-math requirement, to handle arrays of more than 2^31 bytes
103  // - or 2^28 - or about 268M - 8-byte pointer elements.
104  return _Obase + ((long)idx * _Oscale);
105  }
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;
110  // Note the long-math requirement, to handle arrays of more than 2^31 bytes
111  // - or 2^28 - or about 268M - 8-byte pointer elements.
112  return _Lbase + ((long)idx * _Lscale);
113  }
114 
115  // --- Bits to allow Unsafe CAS'ing of the CHM field
116  private static final long _chm_offset = fieldOffset(NonBlockingHashMapLong.class, "_chm");
117  private static final long _val_1_offset = fieldOffset(NonBlockingHashMapLong.class, "_val_1");
118 
119  private final boolean CAS( final long offset, final Object old, final Object nnn ) {
120  return UNSAFE.compareAndSwapObject(this, offset, old, nnn );
121  }
122 
123  // --- Adding a 'prime' bit onto Values via wrapping with a junk wrapper class
124  private static final class Prime {
125  final Object _V;
126  Prime( Object V ) { _V = V; }
127  static Object unbox( Object V ) { return V instanceof Prime ? ((Prime)V)._V : V; }
128  }
129 
130  // --- The Hash Table --------------------
131  private transient CHM _chm;
132  // This next field holds the value for Key 0 - the special key value which
133  // is the initial array value, and also means: no-key-inserted-yet.
134  private transient Object _val_1; // Value for Key: NO_KEY
135 
136  // Time since last resize
137  private transient long _last_resize_milli;
138 
139  // Optimize for space: use a 1/2-sized table and allow more re-probes
140  private final boolean _opt_for_space;
141 
142  // --- Minimum table size ----------------
143  // Pick size 16 K/V pairs, which turns into (16*2)*4+12 = 140 bytes on a
144  // standard 32-bit HotSpot, and (16*2)*8+12 = 268 bytes on 64-bit Azul.
145  private static final int MIN_SIZE_LOG=4; //
146  private static final int MIN_SIZE=(1<<MIN_SIZE_LOG); // Must be power of 2
147 
148  // --- Sentinels -------------------------
149  // No-Match-Old - putIfMatch does updates only if it matches the old value,
150  // and NO_MATCH_OLD basically counts as a wildcard match.
151  private static final Object NO_MATCH_OLD = new Object(); // Sentinel
152  // Match-Any-not-null - putIfMatch does updates only if it find a real old
153  // value.
154  private static final Object MATCH_ANY = new Object(); // Sentinel
155  // This K/V pair has been deleted (but the Key slot is forever claimed).
156  // The same Key can be reinserted with a new value later.
157  private static final Object TOMBSTONE = new Object();
158  // Prime'd or box'd version of TOMBSTONE. This K/V pair was deleted, then a
159  // table resize started. The K/V pair has been marked so that no new
160  // updates can happen to the old table (and since the K/V pair was deleted
161  // nothing was copied to the new table).
162  private static final Prime TOMBPRIME = new Prime(TOMBSTONE);
163 
164  // I exclude 1 long from the 2^64 possibilities, and test for it before
165  // entering the main array. The NO_KEY value must be zero, the initial
166  // value set by Java before it hands me the array.
167  private static final long NO_KEY = 0L;
168 
169  // --- dump ----------------------------------------------------------------
171  public final void print() {
172  System.out.println("=========");
173  print_impl(-99,NO_KEY,_val_1);
174  _chm.print();
175  System.out.println("=========");
176  }
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+")");
182  }
183 
184  private void print2() {
185  System.out.println("=========");
187  _chm.print();
188  System.out.println("=========");
189  }
190  private static void print2_impl(final int i, final long K, final Object V) {
191  if( V != null && Prime.unbox(V) != TOMBSTONE )
192  print_impl(i,K,V);
193  }
194 
195  // Count of reprobes
202  public long reprobes() { long r = _reprobes.get(); _reprobes = new ConcurrentAutoTable(); return r; }
203 
204 
205  // --- reprobe_limit -----------------------------------------------------
206  // Heuristic to decide if we have reprobed toooo many times. Running over
207  // the reprobe limit on a 'get' call acts as a 'miss'; on a 'put' call it
208  // can trigger a table resize. Several places must have exact agreement on
209  // what the reprobe_limit is, so we share it here.
210  private static int reprobe_limit( int len ) {
211  return REPROBE_LIMIT + (len>>4);
212  }
213 
214  // --- NonBlockingHashMapLong ----------------------------------------------
215  // Constructors
216 
219  public NonBlockingHashMapLong( ) { this(MIN_SIZE,true); }
220 
226  public NonBlockingHashMapLong( final int initial_sz ) { this(initial_sz,true); }
227 
232  public NonBlockingHashMapLong( final boolean opt_for_space ) { this(1,opt_for_space); }
233 
238  public NonBlockingHashMapLong( final int initial_sz, final boolean opt_for_space ) {
239  _opt_for_space = opt_for_space;
240  initialize(initial_sz);
241  }
242  private void initialize( final int initial_sz ) {
243  if( initial_sz < 0 ) throw new IllegalArgumentException("initial_sz argument must be >= 0");
244  int i; // Convert to next largest power-of-2
245  for( i=MIN_SIZE_LOG; (1<<i) < initial_sz; i++ ) {/*empty*/}
246  _chm = new CHM(this,new ConcurrentAutoTable(),i);
247  _val_1 = TOMBSTONE; // Always as-if deleted
248  _last_resize_milli = System.currentTimeMillis();
249  }
250 
251  // --- wrappers ------------------------------------------------------------
252 
255  public int size ( ) { return (_val_1==TOMBSTONE?0:1) + _chm.size(); }
258  public boolean containsKey( long key ) { return get(key) != null; }
259 
268  public boolean contains ( Object val ) { return containsValue(val); }
269 
278  public TypeV put ( long key, TypeV val ) { return putIfMatch( key, val,NO_MATCH_OLD);}
279 
286  public TypeV putIfAbsent( long key, TypeV val ) { return putIfMatch( key, val,TOMBSTONE );}
287 
292  public TypeV remove ( long key ) { return putIfMatch( key,TOMBSTONE,NO_MATCH_OLD);}
293 
297  public boolean remove ( long key,Object val ) { return putIfMatch( key,TOMBSTONE,val ) == val ;}
298 
302  public TypeV replace ( long key, TypeV val ) { return putIfMatch( key, val,MATCH_ANY );}
303 
307  public boolean replace ( long key, TypeV oldValue, TypeV newValue ) {
308  return putIfMatch( key, newValue, oldValue ) == oldValue;
309  }
310 
311  @SuppressWarnings("unchecked")
312  private TypeV putIfMatch( long key, Object newVal, Object oldVal ) {
313  if (oldVal == null || newVal == null) throw new NullPointerException();
314  if( key == NO_KEY ) {
315  Object curVal = _val_1;
316  if( oldVal == NO_MATCH_OLD || // Do we care about expected-Value at all?
317  curVal == oldVal || // No instant match already?
318  (oldVal == MATCH_ANY && curVal != TOMBSTONE) ||
319  oldVal.equals(curVal) ) { // Expensive equals check
320  if( !CAS(_val_1_offset,curVal,newVal) ) // One shot CAS update attempt
321  curVal = _val_1; // Failed; get failing witness
322  }
323  return curVal == TOMBSTONE ? null : (TypeV)curVal; // Return the last value present
324  }
325  final Object res = _chm.putIfMatch( key, newVal, oldVal );
326  assert !(res instanceof Prime);
327  assert res != null;
328  return res == TOMBSTONE ? null : (TypeV)res;
329  }
330 
332  public void clear() { // Smack a new empty table down
333  CHM newchm = new CHM(this,new ConcurrentAutoTable(),MIN_SIZE_LOG);
334  while( !CAS(_chm_offset,_chm,newchm) ) { /*Spin until the clear works*/}
336  }
337  // Non-atomic clear, preserving existing large arrays
338  public void clear(boolean large) { // Smack a new empty table down
339  _chm.clear();
341  }
342 
349  public boolean containsValue( Object val ) {
350  if( val == null ) return false;
351  if( val == _val_1 ) return true; // Key 0
352  for( TypeV V : values() )
353  if( V == val || V.equals(val) )
354  return true;
355  return false;
356  }
357 
358  // --- get -----------------------------------------------------------------
366  // Never returns a Prime nor a Tombstone.
367  @SuppressWarnings("unchecked")
368  public final TypeV get( long key ) {
369  if( key == NO_KEY ) {
370  final Object V = _val_1;
371  return V == TOMBSTONE ? null : (TypeV)V;
372  }
373  final Object V = _chm.get_impl(key);
374  assert !(V instanceof Prime); // Never return a Prime
375  assert V != TOMBSTONE;
376  return (TypeV)V;
377  }
378 
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); }
386  public boolean containsKey( Object key ) { return (key instanceof Long) && containsKey(((Long) key).longValue()); }
388  public TypeV putIfAbsent( Long key, TypeV val ) { return putIfAbsent( 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);
396  }
397 
398  // --- help_copy -----------------------------------------------------------
399  // Help along an existing resize operation. This is just a fast cut-out
400  // wrapper, to encourage inlining for the fast no-copy-in-progress case. We
401  // always help the top-most table copy, even if there are nested table
402  // copies in progress.
403  private void help_copy( ) {
404  // Read the top-level CHM only once. We'll try to help this copy along,
405  // even if it gets promoted out from under us (i.e., the copy completes
406  // and another KVS becomes the top-level copy).
407  CHM topchm = _chm;
408  if( topchm._newchm == null ) return; // No copy in-progress
409  topchm.help_copy_impl(false);
410  }
411 
412  // --- hash ----------------------------------------------------------------
413  // Helper function to spread lousy hashCodes Throws NPE for null Key, on
414  // purpose - as the first place to conveniently toss the required NPE for a
415  // null Key.
416  private static final int hash(long h) {
417  h ^= (h>>>20) ^ (h>>>12);
418  h ^= (h>>> 7) ^ (h>>> 4);
419  h += h<<7; // smear low bits up high, for hashcodes that only differ by 1
420  return (int)h;
421  }
422 
423 
424  // --- CHM -----------------------------------------------------------------
425  // The control structure for the NonBlockingHashMapLong
426  private static final class CHM implements Serializable {
427  // Back-pointer to top-level structure
429 
430  // Size in active K,V pairs
432  public int size () { return (int)_size.get(); }
433 
434  // ---
435  // These next 2 fields are used in the resizing heuristics, to judge when
436  // it is time to resize or copy the table. Slots is a count of used-up
437  // key slots, and when it nears a large fraction of the table we probably
438  // end up reprobing too much. Last-resize-milli is the time since the
439  // last resize; if we are running back-to-back resizes without growing
440  // (because there are only a few live keys but many slots full of dead
441  // keys) then we need a larger table to cut down on the churn.
442 
443  // Count of used slots, to tell when table is full of dead unusable slots
445  public int slots() { return (int)_slots.get(); }
446 
447  // ---
448  // New mappings, used during resizing.
449  // The 'next' CHM - created during a resize operation. This represents
450  // the new table being copied from the old one. It's the volatile
451  // variable that is read as we cross from one table to the next, to get
452  // the required memory orderings. It monotonically transits from null to
453  // set (once).
454  volatile CHM _newchm;
455  private static final AtomicReferenceFieldUpdater<CHM,CHM> _newchmUpdater =
456  AtomicReferenceFieldUpdater.newUpdater(CHM.class,CHM.class, "_newchm");
457  // Set the _newchm field if we can. AtomicUpdaters do not fail spuriously.
458  boolean CAS_newchm( CHM newchm ) {
459  return _newchmUpdater.compareAndSet(this,null,newchm);
460  }
461  // Sometimes many threads race to create a new very large table. Only 1
462  // wins the race, but the losers all allocate a junk large table with
463  // hefty allocation costs. Attempt to control the overkill here by
464  // throttling attempts to create a new table. I cannot really block here
465  // (lest I lose the non-blocking property) but late-arriving threads can
466  // give the initial resizing thread a little time to allocate the initial
467  // new table. The Right Long Term Fix here is to use array-lets and
468  // incrementally create the new very large array. In C I'd make the array
469  // with malloc (which would mmap under the hood) which would only eat
470  // virtual-address and not real memory - and after Somebody wins then we
471  // could in parallel initialize the array. Java does not allow
472  // un-initialized array creation (especially of ref arrays!).
473  volatile long _resizers; // count of threads attempting an initial resize
474  private static final AtomicLongFieldUpdater<CHM> _resizerUpdater =
475  AtomicLongFieldUpdater.newUpdater(CHM.class, "_resizers");
476 
477  // --- key,val -------------------------------------------------------------
478  // Access K,V for a given idx
479  private boolean CAS_key( int idx, long old, long key ) {
480  return UNSAFE.compareAndSwapLong ( _keys, rawIndex(_keys, idx), old, key );
481  }
482  private boolean CAS_val( int idx, Object old, Object val ) {
483  return UNSAFE.compareAndSwapObject( _vals, rawIndex(_vals, idx), old, val );
484  }
485 
486  final long [] _keys;
487  final Object [] _vals;
488 
489  // Simple constructor
490  CHM( final NonBlockingHashMapLong nbhml, ConcurrentAutoTable size, final int logsize ) {
491  _nbhml = nbhml;
492  _size = size;
494  _keys = new long [1<<logsize];
495  _vals = new Object[1<<logsize];
496  }
497  // Non-atomic clear
498  void clear() {
499  _size = new ConcurrentAutoTable();
501  Arrays.fill(_keys,0);
502  Arrays.fill(_vals,null);
503  }
504 
505  // --- print innards
506  private void print() {
507  for( int i=0; i<_keys.length; i++ ) {
508  long K = _keys[i];
509  if( K != NO_KEY )
510  print_impl(i,K,_vals[i]);
511  }
512  CHM newchm = _newchm; // New table, if any
513  if( newchm != null ) {
514  System.out.println("----");
515  newchm.print();
516  }
517  }
518 
519  // --- print only the live objects
520  private void print2( ) {
521  for( int i=0; i<_keys.length; i++ ) {
522  long K = _keys[i];
523  if( K != NO_KEY ) // key is sane
524  print2_impl(i,K,_vals[i]);
525  }
526  CHM newchm = _newchm; // New table, if any
527  if( newchm != null ) {
528  System.out.println("----");
529  newchm.print2();
530  }
531  }
532 
533  // --- get_impl ----------------------------------------------------------
534  // Never returns a Prime nor a Tombstone.
535  private Object get_impl ( final long key ) {
536  final int hash = hash(key);
537  final int len = _keys.length;
538  int idx = (hash & (len-1)); // First key hash
539 
540  // Main spin/reprobe loop, looking for a Key hit
541  int reprobe_cnt=0;
542  while( true ) {
543  final long K = _keys[idx]; // Get key before volatile read, could be NO_KEY
544  final Object V = _vals[idx]; // Get value before volatile read, could be null or Tombstone or Prime
545  if( K == NO_KEY ) return null; // A clear miss
546 
547  // Key-compare
548  if( key == K ) {
549  // Key hit! Check for no table-copy-in-progress
550  if( !(V instanceof Prime) ) { // No copy?
551  if( V == TOMBSTONE) return null;
552  // We need a volatile-read between reading a newly inserted Value
553  // and returning the Value (so the user might end up reading the
554  // stale Value contents).
555  @SuppressWarnings("unused") final CHM newchm = _newchm; // VOLATILE READ before returning V
556  return V;
557  }
558  // Key hit - but slot is (possibly partially) copied to the new table.
559  // Finish the copy & retry in the new table.
560  return copy_slot_and_check(idx,key).get_impl(key); // Retry in the new table
561  }
562  // get and put must have the same key lookup logic! But only 'put'
563  // needs to force a table-resize for a too-long key-reprobe sequence.
564  // Check for too-many-reprobes on get.
565  if( ++reprobe_cnt >= reprobe_limit(len) ) // too many probes
566  return _newchm == null // Table copy in progress?
567  ? null // Nope! A clear miss
568  : copy_slot_and_check(idx,key).get_impl(key); // Retry in the new table
569 
570  idx = (idx+1)&(len-1); // Reprobe by 1! (could now prefetch)
571  }
572  }
573 
574  // --- putIfMatch ---------------------------------------------------------
575  // Put, Remove, PutIfAbsent, etc. Return the old value. If the returned
576  // value is equal to expVal (or expVal is NO_MATCH_OLD) then the put can
577  // be assumed to work (although might have been immediately overwritten).
578  // Only the path through copy_slot passes in an expected value of null,
579  // and putIfMatch only returns a null if passed in an expected null.
580  private static volatile int DUMMY_VOLATILE;
581  private Object putIfMatch( final long key, final Object putval, final Object expVal ) {
582  final int hash = hash(key);
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)); // The first key
588 
589  // ---
590  // Key-Claim stanza: spin till we can claim a Key (or force a resizing).
591  int reprobe_cnt=0;
592  long K;
593  Object V;
594  while( true ) { // Spin till we get a Key slot
595  V = _vals[idx]; // Get old value
596  K = _keys[idx]; // Get current key
597  if( K == NO_KEY ) { // Slot is free?
598  // Found an empty Key slot - which means this Key has never been in
599  // this table. No need to put a Tombstone - the Key is not here!
600  if( putval == TOMBSTONE ) return TOMBSTONE; // Not-now & never-been in this table
601  if( expVal == MATCH_ANY ) return TOMBSTONE; // Will not match, even after K inserts
602  // Claim the zero key-slot
603  if( CAS_key(idx, NO_KEY, key) ) { // Claim slot for Key
604  _slots.add(1); // Raise key-slots-used count
605  break; // Got it!
606  }
607  // CAS to claim the key-slot failed.
608  //
609  // This re-read of the Key points out an annoying short-coming of Java
610  // CAS. Most hardware CAS's report back the existing value - so that
611  // if you fail you have a *witness* - the value which caused the CAS
612  // to fail. The Java API turns this into a boolean destroying the
613  // witness. Re-reading does not recover the witness because another
614  // thread can write over the memory after the CAS. Hence we can be in
615  // the unfortunate situation of having a CAS fail *for cause* but
616  // having that cause removed by a later store. This turns a
617  // non-spurious-failure CAS (such as Azul has) into one that can
618  // apparently spuriously fail - and we avoid apparent spurious failure
619  // by not allowing Keys to ever change.
620  K = _keys[idx]; // CAS failed, get updated value
621  assert K != NO_KEY ; // If keys[idx] is NO_KEY, CAS shoulda worked
622  }
623  // Key slot was not null, there exists a Key here
624  if( K == key )
625  break; // Got it!
626 
627  // get and put must have the same key lookup logic! Lest 'get' give
628  // up looking too soon.
629  //topmap._reprobes.add(1);
630  if( ++reprobe_cnt >= reprobe_limit(len) ) {
631  // We simply must have a new table to do a 'put'. At this point a
632  // 'get' will also go to the new table (if any). We do not need
633  // to claim a key slot (indeed, we cannot find a free one to claim!).
634  final CHM newchm = resize();
635  if( expVal != null ) _nbhml.help_copy(); // help along an existing copy
636  return newchm.putIfMatch(key,putval,expVal);
637  }
638 
639  idx = (idx+1)&(len-1); // Reprobe!
640  } // End of spinning till we get a Key slot
641 
642  while ( true ) { // Spin till we insert a value
643  // ---
644  // Found the proper Key slot, now update the matching Value slot. We
645  // never put a null, so Value slots monotonically move from null to
646  // not-null (deleted Values use Tombstone). Thus if 'V' is null we
647  // fail this fast cutout and fall into the check for table-full.
648  if( putval == V ) return V; // Fast cutout for no-change
649 
650  // See if we want to move to a new table (to avoid high average re-probe
651  // counts). We only check on the initial set of a Value from null to
652  // not-null (i.e., once per key-insert).
653  if( (V == null && tableFull(reprobe_cnt,len)) ||
654  // Or we found a Prime: resize is already in progress. The resize
655  // call below will do a CAS on _newchm forcing the read.
656  V instanceof Prime) {
657  resize(); // Force the new table copy to start
658  return copy_slot_and_check(idx,expVal).putIfMatch(key,putval,expVal);
659  }
660 
661  // ---
662  // We are finally prepared to update the existing table
663  //assert !(V instanceof Prime); // always true, so IDE warnings if uncommented
664 
665  // Must match old, and we do not? Then bail out now. Note that either V
666  // or expVal might be TOMBSTONE. Also V can be null, if we've never
667  // inserted a value before. expVal can be null if we are called from
668  // copy_slot.
669 
670  if( expVal != NO_MATCH_OLD && // Do we care about expected-Value at all?
671  V != expVal && // No instant match already?
672  (expVal != MATCH_ANY || V == TOMBSTONE || V == null) &&
673  !(V==null && expVal == TOMBSTONE) && // Match on null/TOMBSTONE combo
674  (expVal == null || !expVal.equals(V)) ) // Expensive equals check at the last
675  return (V==null) ? TOMBSTONE : V; // Do not update!
676 
677  // Actually change the Value in the Key,Value pair
678  if( CAS_val(idx, V, putval ) ) break;
679 
680  // CAS failed
681  // Because we have no witness, we do not know why it failed.
682  // Indeed, by the time we look again the value under test might have flipped
683  // a thousand times and now be the expected value (despite the CAS failing).
684  // Check for the never-succeed condition of a Prime value and jump to any
685  // nested table, or else just re-run.
686 
687  // We would not need this load at all if CAS returned the value on which
688  // the CAS failed (AKA witness). The new CAS semantics are supported via
689  // VarHandle in JDK9.
690  V = _vals[idx]; // Get new value
691 
692  // If a Prime'd value got installed, we need to re-run the put on the
693  // new table. Otherwise we lost the CAS to another racing put.
694  // Simply retry from the start.
695  if( V instanceof Prime )
696  return copy_slot_and_check(idx,expVal).putIfMatch(key,putval,expVal);
697 
698  // Simply retry from the start.
699  // NOTE: need the fence, since otherwise '_vals[idx]' load could be hoisted
700  // out of loop.
701  int dummy = DUMMY_VOLATILE;
702  }
703 
704  // CAS succeeded - we did the update!
705  // Both normal put's and table-copy calls putIfMatch, but table-copy
706  // does not (effectively) increase the number of live k/v pairs.
707  if( expVal != null ) {
708  // Adjust sizes - a striped counter
709  if( (V == null || V == TOMBSTONE) && putval != TOMBSTONE ) _size.add( 1);
710  if( !(V == null || V == TOMBSTONE) && putval == TOMBSTONE ) _size.add(-1);
711  }
712 
713  // We won; we know the update happened as expected.
714  return (V==null && expVal!=null) ? TOMBSTONE : V;
715  }
716 
717  // --- tableFull ---------------------------------------------------------
718  // Heuristic to decide if this table is too full, and we should start a
719  // new table. Note that if a 'get' call has reprobed too many times and
720  // decided the table must be full, then always the estimate_sum must be
721  // high and we must report the table is full. If we do not, then we might
722  // end up deciding that the table is not full and inserting into the
723  // current table, while a 'get' has decided the same key cannot be in this
724  // table because of too many reprobes. The invariant is:
725  // slots.estimate_sum >= max_reprobe_cnt >= reprobe_limit(len)
726  private boolean tableFull( int reprobe_cnt, int len ) {
727  return
728  // Do the cheap check first: we allow some number of reprobes always
729  reprobe_cnt >= REPROBE_LIMIT &&
730  (reprobe_cnt >= reprobe_limit(len) ||
731  // More expensive check: see if the table is > 1/2 full.
732  _slots.estimate_get() >= (len>>1));
733  }
734 
735  // --- resize ------------------------------------------------------------
736  // Resizing after too many probes. "How Big???" heuristics are here.
737  // Callers will (not this routine) will 'help_copy' any in-progress copy.
738  // Since this routine has a fast cutout for copy-already-started, callers
739  // MUST 'help_copy' lest we have a path which forever runs through
740  // 'resize' only to discover a copy-in-progress which never progresses.
741  private CHM resize() {
742  // Check for resize already in progress, probably triggered by another thread
743  CHM newchm = _newchm; // VOLATILE READ
744  if( newchm != null ) // See if resize is already in progress
745  return newchm; // Use the new table already
746 
747  // No copy in-progress, so start one. First up: compute new table size.
748  int oldlen = _keys.length; // Old count of K,V pairs allowed
749  int sz = size(); // Get current table count of active K,V pairs
750  int newsz = sz; // First size estimate
751 
752  // Heuristic to determine new size. We expect plenty of dead-slots-with-keys
753  // and we need some decent padding to avoid endless reprobing.
754  if( _nbhml._opt_for_space ) {
755  // This heuristic leads to a much denser table with a higher reprobe rate
756  if( sz >= (oldlen>>1) ) // If we are >50% full of keys then...
757  newsz = oldlen<<1; // Double size
758  } else {
759  if( sz >= (oldlen>>2) ) { // If we are >25% full of keys then...
760  newsz = oldlen<<1; // Double size
761  if( sz >= (oldlen>>1) ) // If we are >50% full of keys then...
762  newsz = oldlen<<2; // Double double size
763  }
764  }
765 
766  // Last (re)size operation was very recent? Then double again
767  // despite having few live keys; slows down resize operations
768  // for tables subject to a high key churn rate - but do not
769  // forever grow the table. If there is a high key churn rate
770  // the table needs a steady state of rare same-size resize
771  // operations to clean out the dead keys.
772  long tm = System.currentTimeMillis();
773  if( newsz <= oldlen && // New table would shrink or hold steady?
774  tm <= _nbhml._last_resize_milli+10000) // Recent resize (less than 10 sec ago)
775  newsz = oldlen<<1; // Double the existing size
776 
777  // Do not shrink, ever. If we hit this size once, assume we
778  // will again.
779  if( newsz < oldlen ) newsz = oldlen;
780 
781  // Convert to power-of-2
782  int log2;
783  for( log2=MIN_SIZE_LOG; (1<<log2) < newsz; log2++ ) ; // Compute log2 of size
784  long len = ((1L << log2) << 1) + 2;
785  // prevent integer overflow - limit of 2^31 elements in a Java array
786  // so here, 2^30 + 2 is the largest number of elements in the hash table
787  if ((int)len!=len) {
788  log2 = 30;
789  len = (1L << log2) + 2;
790  if (sz > ((len >> 2) + (len >> 1))) throw new RuntimeException("Table is full.");
791  }
792 
793  // Now limit the number of threads actually allocating memory to a
794  // handful - lest we have 750 threads all trying to allocate a giant
795  // resized array.
796  long r = _resizers;
797  while( !_resizerUpdater.compareAndSet(this,r,r+1) )
798  r = _resizers;
799  // Size calculation: 2 words (K+V) per table entry, plus a handful. We
800  // guess at 64-bit pointers; 32-bit pointers screws up the size calc by
801  // 2x but does not screw up the heuristic very much.
802  long megs = ((((1L<<log2)<<1)+8)<<3/*word to bytes*/)>>20/*megs*/;
803  if( r >= 2 && megs > 0 ) { // Already 2 guys trying; wait and see
804  newchm = _newchm; // Between dorking around, another thread did it
805  if( newchm != null ) // See if resize is already in progress
806  return newchm; // Use the new table already
807  // We could use a wait with timeout, so we'll wakeup as soon as the new table
808  // is ready, or after the timeout in any case.
809  //synchronized( this ) { wait(8*megs); } // Timeout - we always wakeup
810  // For now, sleep a tad and see if the 2 guys already trying to make
811  // the table actually get around to making it happen.
812  try { Thread.sleep(megs); } catch( Exception e ) { /*empty*/}
813  }
814  // Last check, since the 'new' below is expensive and there is a chance
815  // that another thread slipped in a new thread while we ran the heuristic.
816  newchm = _newchm;
817  if( newchm != null ) // See if resize is already in progress
818  return newchm; // Use the new table already
819 
820  // New CHM - actually allocate the big arrays
821  newchm = new CHM(_nbhml,_size,log2);
822 
823  // Another check after the slow allocation
824  if( _newchm != null ) // See if resize is already in progress
825  return _newchm; // Use the new table already
826 
827  // The new table must be CAS'd in so only 1 winner amongst duplicate
828  // racing resizing threads. Extra CHM's will be GC'd.
829  if( CAS_newchm( newchm ) ) { // NOW a resize-is-in-progress!
830  //notifyAll(); // Wake up any sleepers
831  //long nano = System.nanoTime();
832  //System.out.println(" "+nano+" Resize from "+oldlen+" to "+(1<<log2)+" and had "+(_resizers-1)+" extras" );
833  //System.out.print("["+log2);
834  } else // CAS failed?
835  newchm = _newchm; // Reread new table
836  return newchm;
837  }
838 
839 
840  // The next part of the table to copy. It monotonically transits from zero
841  // to _keys.length. Visitors to the table can claim 'work chunks' by
842  // CAS'ing this field up, then copying the indicated indices from the old
843  // table to the new table. Workers are not required to finish any chunk;
844  // the counter simply wraps and work is copied duplicately until somebody
845  // somewhere completes the count.
846  volatile long _copyIdx = 0;
847  static private final AtomicLongFieldUpdater<CHM> _copyIdxUpdater =
848  AtomicLongFieldUpdater.newUpdater(CHM.class, "_copyIdx");
849 
850  // Work-done reporting. Used to efficiently signal when we can move to
851  // the new table. From 0 to len(oldkvs) refers to copying from the old
852  // table to the new.
853  volatile long _copyDone= 0;
854  static private final AtomicLongFieldUpdater<CHM> _copyDoneUpdater =
855  AtomicLongFieldUpdater.newUpdater(CHM.class, "_copyDone");
856 
857  // --- help_copy_impl ----------------------------------------------------
858  // Help along an existing resize operation. We hope its the top-level
859  // copy (it was when we started) but this CHM might have been promoted out
860  // of the top position.
861  private void help_copy_impl( final boolean copy_all ) {
862  final CHM newchm = _newchm;
863  assert newchm != null; // Already checked by caller
864  int oldlen = _keys.length; // Total amount to copy
865  final int MIN_COPY_WORK = Math.min(oldlen,1024); // Limit per-thread work
866 
867  // ---
868  int panic_start = -1;
869  int copyidx=-9999; // Fool javac to think it's initialized
870  while( _copyDone < oldlen ) { // Still needing to copy?
871  // Carve out a chunk of work. The counter wraps around so every
872  // thread eventually tries to copy every slot repeatedly.
873 
874  // We "panic" if we have tried TWICE to copy every slot - and it still
875  // has not happened. i.e., twice some thread somewhere claimed they
876  // would copy 'slot X' (by bumping _copyIdx) but they never claimed to
877  // have finished (by bumping _copyDone). Our choices become limited:
878  // we can wait for the work-claimers to finish (and become a blocking
879  // algorithm) or do the copy work ourselves. Tiny tables with huge
880  // thread counts trying to copy the table often 'panic'.
881  if( panic_start == -1 ) { // No panic?
882  copyidx = (int)_copyIdx;
883  while( copyidx < (oldlen<<1) && // 'panic' check
884  !_copyIdxUpdater.compareAndSet(this,copyidx,copyidx+MIN_COPY_WORK) )
885  copyidx = (int)_copyIdx; // Re-read
886  if( !(copyidx < (oldlen<<1)) ) // Panic!
887  panic_start = copyidx; // Record where we started to panic-copy
888  }
889 
890  // We now know what to copy. Try to copy.
891  int workdone = 0;
892  for( int i=0; i<MIN_COPY_WORK; i++ )
893  if( copy_slot((copyidx+i)&(oldlen-1)) ) // Made an oldtable slot go dead?
894  workdone++; // Yes!
895  if( workdone > 0 ) // Report work-done occasionally
896  copy_check_and_promote( workdone );// See if we can promote
897  //for( int i=0; i<MIN_COPY_WORK; i++ )
898  // if( copy_slot((copyidx+i)&(oldlen-1)) ) // Made an oldtable slot go dead?
899  // copy_check_and_promote( 1 );// See if we can promote
900 
901  copyidx += MIN_COPY_WORK;
902  // Uncomment these next 2 lines to turn on incremental table-copy.
903  // Otherwise this thread continues to copy until it is all done.
904  if( !copy_all && panic_start == -1 ) // No panic?
905  return; // Then done copying after doing MIN_COPY_WORK
906  }
907  // Extra promotion check, in case another thread finished all copying
908  // then got stalled before promoting.
909  copy_check_and_promote( 0 ); // See if we can promote
910  }
911 
912 
913  // --- copy_slot_and_check -----------------------------------------------
914  // Copy slot 'idx' from the old table to the new table. If this thread
915  // confirmed the copy, update the counters and check for promotion.
916  //
917  // Returns the result of reading the volatile _newchm, mostly as a
918  // convenience to callers. We come here with 1-shot copy requests
919  // typically because the caller has found a Prime, and has not yet read
920  // the _newchm volatile - which must have changed from null-to-not-null
921  // before any Prime appears. So the caller needs to read the _newchm
922  // field to retry his operation in the new table, but probably has not
923  // read it yet.
924  private CHM copy_slot_and_check( int idx, Object should_help ) {
925  // We're only here because the caller saw a Prime, which implies a
926  // table-copy is in progress.
927  assert _newchm != null;
928  if( copy_slot(idx) ) // Copy the desired slot
929  copy_check_and_promote(1); // Record the slot copied
930  // Generically help along any copy (except if called recursively from a helper)
931  if( should_help != null ) _nbhml.help_copy();
932  return _newchm;
933  }
934 
935  // --- copy_check_and_promote --------------------------------------------
936  private void copy_check_and_promote( int workdone ) {
937  int oldlen = _keys.length;
938  // We made a slot unusable and so did some of the needed copy work
939  long copyDone = _copyDone;
940  long nowDone = copyDone+workdone;
941  assert nowDone <= oldlen;
942  if( workdone > 0 ) {
943  while( !_copyDoneUpdater.compareAndSet(this,copyDone,nowDone) ) {
944  copyDone = _copyDone; // Reload, retry
945  nowDone = copyDone+workdone;
946  assert nowDone <= oldlen;
947  }
948  }
949 
950  // Check for copy being ALL done, and promote. Note that we might have
951  // nested in-progress copies and manage to finish a nested copy before
952  // finishing the top-level copy. We only promote top-level copies.
953  if( nowDone == oldlen && // Ready to promote this table?
954  _nbhml._chm == this && // Looking at the top-level table?
955  // Attempt to promote
956  _nbhml.CAS(_chm_offset,this,_newchm) ) {
957  _nbhml._last_resize_milli = System.currentTimeMillis(); // Record resize time for next check
958  }
959  }
960 
961  // --- copy_slot ---------------------------------------------------------
962  // Copy one K/V pair from oldkvs[i] to newkvs. Returns true if we can
963  // confirm that we set an old-table slot to TOMBPRIME, and only returns after
964  // updating the new table. We need an accurate confirmed-copy count so
965  // that we know when we can promote (if we promote the new table too soon,
966  // other threads may 'miss' on values not-yet-copied from the old table).
967  // We don't allow any direct updates on the new table, unless they first
968  // happened to the old table - so that any transition in the new table from
969  // null to not-null must have been from a copy_slot (or other old-table
970  // overwrite) and not from a thread directly writing in the new table.
971  private boolean copy_slot( int idx ) {
972  // Blindly set the key slot from NO_KEY to some key which hashes here,
973  // to eagerly stop fresh put's from inserting new values in the old
974  // table when the old table is mid-resize. We don't need to act on the
975  // results here, because our correctness stems from box'ing the Value
976  // field. Slamming the Key field is a minor speed optimization.
977  long key;
978  while( (key=_keys[idx]) == NO_KEY )
979  CAS_key(idx, NO_KEY, (idx+_keys.length)/*a non-zero key which hashes here*/);
980 
981  // ---
982  // Prevent new values from appearing in the old table.
983  // Box what we see in the old table, to prevent further updates.
984  Object oldval = _vals[idx]; // Read OLD table
985  while( !(oldval instanceof Prime) ) {
986  final Prime box = (oldval == null || oldval == TOMBSTONE) ? TOMBPRIME : new Prime(oldval);
987  if( CAS_val(idx,oldval,box) ) { // CAS down a box'd version of oldval
988  // If we made the Value slot hold a TOMBPRIME, then we both
989  // prevented further updates here but also the (absent) oldval is
990  // vaccuously available in the new table. We return with true here:
991  // any thread looking for a value for this key can correctly go
992  // straight to the new table and skip looking in the old table.
993  if( box == TOMBPRIME )
994  return true;
995  // Otherwise we boxed something, but it still needs to be
996  // copied into the new table.
997  oldval = box; // Record updated oldval
998  break; // Break loop; oldval is now boxed by us
999  }
1000  oldval = _vals[idx]; // Else try, try again
1001  }
1002  if( oldval == TOMBPRIME ) return false; // Copy already complete here!
1003 
1004  // ---
1005  // Copy the value into the new table, but only if we overwrite a null.
1006  // If another value is already in the new table, then somebody else
1007  // wrote something there and that write is happens-after any value that
1008  // appears in the old table.
1009  Object old_unboxed = ((Prime)oldval)._V;
1010  assert old_unboxed != TOMBSTONE;
1011  boolean copied_into_new = (_newchm.putIfMatch(key, old_unboxed, null) == null);
1012 
1013  // ---
1014  // Finally, now that any old value is exposed in the new table, we can
1015  // forever hide the old-table value by slapping a TOMBPRIME down. This
1016  // will stop other threads from uselessly attempting to copy this slot
1017  // (i.e., it's a speed optimization not a correctness issue).
1018  while( oldval != TOMBPRIME && !CAS_val(idx,oldval,TOMBPRIME) )
1019  oldval = _vals[idx];
1020 
1021  return copied_into_new;
1022  } // end copy_slot
1023  } // End of CHM
1024 
1025 
1026  // --- Snapshot ------------------------------------------------------------
1027  // The main class for iterating over the NBHM. It "snapshots" a clean
1028  // view of the K/V array.
1029  private class SnapshotV implements Iterator<TypeV>, Enumeration<TypeV> {
1030  final CHM _sschm;
1031  public SnapshotV() {
1032  CHM topchm;
1033  while( true ) { // Verify no table-copy-in-progress
1034  topchm = _chm;
1035  if( topchm._newchm == null ) // No table-copy-in-progress
1036  break;
1037  // Table copy in-progress - so we cannot get a clean iteration. We
1038  // must help finish the table copy before we can start iterating.
1039  topchm.help_copy_impl(true);
1040  }
1041  // The "linearization point" for the iteration. Every key in this table
1042  // will be visited, but keys added later might be skipped or even be
1043  // added to a following table (also not iterated over).
1044  _sschm = topchm;
1045  // Warm-up the iterator
1046  _idx = -1;
1047  next();
1048  }
1049  int length() { return _sschm._keys.length; }
1050  long key(final int idx) { return _sschm._keys[idx]; }
1051  private int _idx; // -2 for NO_KEY, -1 for CHECK_NEW_TABLE_LONG, 0-keys.length
1052  private long _nextK, _prevK; // Last 2 keys found
1053  private TypeV _nextV, _prevV; // Last 2 values found
1054  public boolean hasNext() { return _nextV != null; }
1055  public TypeV next() {
1056  // 'next' actually knows what the next value will be - it had to
1057  // figure that out last go 'round lest 'hasNext' report true and
1058  // some other thread deleted the last value. Instead, 'next'
1059  // spends all its effort finding the key that comes after the
1060  // 'next' key.
1061  if( _idx != -1 && _nextV == null ) throw new NoSuchElementException();
1062  _prevK = _nextK; // This will become the previous key
1063  _prevV = _nextV; // This will become the previous value
1064  _nextV = null; // We have no more next-key
1065  // Attempt to set <_nextK,_nextV> to the next K,V pair.
1066  // _nextV is the trigger: stop searching when it is != null
1067  if( _idx == -1 ) { // Check for NO_KEY
1068  _idx = 0; // Setup for next phase of search
1069  _nextK = NO_KEY;
1070  if( (_nextV=get(_nextK)) != null ) return _prevV;
1071  }
1072  while( _idx<length() ) { // Scan array
1073  _nextK = key(_idx++); // Get a key that definitely is in the set (for the moment!)
1074  if( _nextK != NO_KEY && // Found something?
1075  (_nextV=get(_nextK)) != null )
1076  break; // Got it! _nextK is a valid Key
1077  } // Else keep scanning
1078  return _prevV; // Return current value.
1079  }
1080 
1081  public void removeKey() {
1082  if( _prevV == null ) throw new IllegalStateException();
1084  _prevV = null;
1085  }
1086 
1087  @Override
1088  public void remove() {
1089  // NOTE: it would seem logical that value removal will semantically mean
1090  // removing the matching value for the mapping <k,v>, but the JDK always
1091  // removes by key, even when the value has changed.
1092  removeKey();
1093  }
1094 
1095  public TypeV nextElement() { return next(); }
1096  public boolean hasMoreElements() { return hasNext(); }
1097  }
1098 
1102  public Enumeration<TypeV> elements() { return new SnapshotV(); }
1103 
1104  // --- values --------------------------------------------------------------
1118  public Collection<TypeV> values() {
1119  return new AbstractCollection<TypeV>() {
1120  public void clear ( ) { NonBlockingHashMapLong.this.clear ( ); }
1121  public int size ( ) { return NonBlockingHashMapLong.this.size ( ); }
1122  public boolean contains( Object v ) { return NonBlockingHashMapLong.this.containsValue(v); }
1123  public Iterator<TypeV> iterator() { return new SnapshotV(); }
1124  };
1125  }
1126 
1127  // --- keySet --------------------------------------------------------------
1131  public class IteratorLong implements Iterator<Long>, Enumeration<Long> {
1132  private final SnapshotV _ss;
1134  public IteratorLong() { _ss = new SnapshotV(); }
1136  public void remove() { _ss.removeKey(); }
1138  public Long next () { _ss.next(); return _ss._prevK; }
1140  public long nextLong() { _ss.next(); return _ss._prevK; }
1142  public boolean hasNext() { return _ss.hasNext(); }
1144  public Long nextElement() { return next(); }
1146  public boolean hasMoreElements() { return hasNext(); }
1147  }
1152  public Enumeration<Long> keys() { return new IteratorLong(); }
1153 
1168  public Set<Long> keySet() {
1169  return new AbstractSet<Long> () {
1170  public void clear ( ) { NonBlockingHashMapLong.this.clear ( ); }
1171  public int size ( ) { return NonBlockingHashMapLong.this.size ( ); }
1172  public boolean contains( Object k ) { return NonBlockingHashMapLong.this.containsKey(k); }
1173  public boolean remove ( Object k ) { return NonBlockingHashMapLong.this.remove (k) != null; }
1174  public IteratorLong iterator() { return new IteratorLong(); }
1175  };
1176  }
1177 
1179  @SuppressWarnings("unchecked")
1180  public long[] keySetLong() {
1181  long[] dom = new long[size()];
1182  IteratorLong i=(IteratorLong)keySet().iterator();
1183  int j=0;
1184  while( j < dom.length && i.hasNext() )
1185  dom[j++] = i.nextLong();
1186  return dom;
1187  }
1188 
1189  // --- entrySet ------------------------------------------------------------
1190  // Warning: Each call to 'next' in this iterator constructs a new Long and a
1191  // new NBHMLEntry.
1192  private class NBHMLEntry extends AbstractEntry<Long,TypeV> {
1193  NBHMLEntry( final Long k, final TypeV v ) { super(k,v); }
1194  public TypeV setValue(final TypeV val) {
1195  if (val == null) throw new NullPointerException();
1196  _val = val;
1197  return put(_key, val);
1198  }
1199  }
1200  private class SnapshotE implements Iterator<Map.Entry<Long,TypeV>> {
1202  public SnapshotE() { _ss = new SnapshotV(); }
1203  public void remove() {
1204  // NOTE: it would seem logical that entry removal will semantically mean
1205  // removing the matching pair <k,v>, but the JDK always removes by key,
1206  // even when the value has changed.
1207  _ss.removeKey();
1208  }
1209  public Map.Entry<Long,TypeV> next() { _ss.next(); return new NBHMLEntry(_ss._prevK,_ss._prevV); }
1210  public boolean hasNext() { return _ss.hasNext(); }
1211  }
1212 
1235  public Set<Map.Entry<Long,TypeV>> entrySet() {
1236  return new AbstractSet<Map.Entry<Long,TypeV>>() {
1237  public void clear ( ) { NonBlockingHashMapLong.this.clear( ); }
1238  public int size ( ) { return NonBlockingHashMapLong.this.size ( ); }
1239  public boolean remove( final Object o ) {
1240  if (!(o instanceof Map.Entry)) return false;
1241  final Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1242  return NonBlockingHashMapLong.this.remove(e.getKey(), e.getValue());
1243  }
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());
1249  }
1250  public Iterator<Map.Entry<Long,TypeV>> iterator() { return new SnapshotE(); }
1251  };
1252  }
1253 
1254  // --- writeObject -------------------------------------------------------
1255  // Write a NBHML to a stream
1256  private void writeObject(java.io.ObjectOutputStream s) throws IOException {
1257  s.defaultWriteObject(); // Write nothing
1258  for( long K : keySet() ) {
1259  final Object V = get(K); // Do an official 'get'
1260  s.writeLong (K); // Write the <long,TypeV> pair
1261  s.writeObject(V);
1262  }
1263  s.writeLong(NO_KEY); // Sentinel to indicate end-of-data
1264  s.writeObject(null);
1265  }
1266 
1267  // --- readObject --------------------------------------------------------
1268  // Read a CHM from a stream
1269  @SuppressWarnings("unchecked")
1270  private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
1271  s.defaultReadObject(); // Read nothing
1273  for (;;) {
1274  final long K = s.readLong();
1275  final TypeV V = (TypeV) s.readObject();
1276  if( K == NO_KEY && V == null ) break;
1277  put(K,V); // Insert with an offical put
1278  }
1279  }
1280 
1288  @SuppressWarnings("unchecked")
1289  @Override
1291  try {
1292  // Must clone, to get the class right; NBHML might have been
1293  // extended so it would be wrong to just make a new NBHML.
1295  // But I don't have an atomic clone operation - the underlying _kvs
1296  // structure is undergoing rapid change. If I just clone the _kvs
1297  // field, the CHM in _kvs[0] won't be in sync.
1298  //
1299  // Wipe out the cloned array (it was shallow anyways).
1300  t.clear();
1301  // Now copy sanely
1302  for( long K : keySetLong() )
1303  t.put(K,get(K));
1304  return t;
1305  } catch (CloneNotSupportedException e) {
1306  // this shouldn't happen, since we are Cloneable
1307  throw new InternalError();
1308  }
1309  }
1310 
1311 } // End NonBlockingHashMapLong class
com.cliffc.aa.util.NonBlockingHashMapLong.elements
Enumeration< TypeV > elements()
Returns an enumeration of the values in this table.
Definition: NonBlockingHashMapLong.java:1102
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._slots
ConcurrentAutoTable _slots
Definition: NonBlockingHashMapLong.java:444
com.cliffc.aa.util.NonBlockingHashMapLong.NBHMLEntry.NBHMLEntry
NBHMLEntry(final Long k, final TypeV v)
Definition: NonBlockingHashMapLong.java:1193
com.cliffc.aa.util.NonBlockingHashMapLong._chm
transient CHM _chm
Definition: NonBlockingHashMapLong.java:131
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.copy_slot_and_check
CHM copy_slot_and_check(int idx, Object should_help)
Definition: NonBlockingHashMapLong.java:924
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.help_copy_impl
void help_copy_impl(final boolean copy_all)
Definition: NonBlockingHashMapLong.java:861
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.size
int size()
Definition: NonBlockingHashMapLong.java:432
com.cliffc.aa.util.NonBlockingHashMapLong.rawIndex
static long rawIndex(final long[] ary, final int idx)
Definition: NonBlockingHashMapLong.java:108
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._sschm
final CHM _sschm
Definition: NonBlockingHashMapLong.java:1030
com.cliffc.aa.util.NonBlockingHashMapLong.REPROBE_LIMIT
static final int REPROBE_LIMIT
Definition: NonBlockingHashMapLong.java:95
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong._ss
final SnapshotV _ss
Definition: NonBlockingHashMapLong.java:1132
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.clear
void clear()
Definition: NonBlockingHashMapLong.java:498
com.cliffc.aa.util.NonBlockingHashMapLong.NonBlockingHashMapLong
NonBlockingHashMapLong()
Create a new NonBlockingHashMapLong with default minimum size (currently set to 8 K/V pairs or roughl...
Definition: NonBlockingHashMapLong.java:219
com.cliffc.aa.util.NonBlockingHashMapLong.keySetLong
long[] keySetLong()
Keys as a long array.
Definition: NonBlockingHashMapLong.java:1180
com.cliffc.aa.util.NonBlockingHashMapLong.print
final void print()
Verbose printout of table internals, useful for debugging.
Definition: NonBlockingHashMapLong.java:171
com.cliffc
com.cliffc.aa.util.NonBlockingHashMapLong._reprobes
transient ConcurrentAutoTable _reprobes
Definition: NonBlockingHashMapLong.java:196
com.cliffc.aa.util.NonBlockingHashMapLong.putIfAbsent
TypeV putIfAbsent(Long key, TypeV val)
Auto-boxing version of putIfAbsent.
Definition: NonBlockingHashMapLong.java:388
com.cliffc.aa.util.NonBlockingHashMapLong.keys
Enumeration< Long > keys()
Returns an enumeration of the auto-boxed keys in this table.
Definition: NonBlockingHashMapLong.java:1152
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._size
ConcurrentAutoTable _size
Definition: NonBlockingHashMapLong.java:431
com.cliffc.aa.util.NonBlockingHashMapLong.MIN_SIZE_LOG
static final int MIN_SIZE_LOG
Definition: NonBlockingHashMapLong.java:145
com.cliffc.aa.util.NonBlockingHashMapLong.replace
TypeV replace(Long key, TypeV Val)
Auto-boxing version of replace.
Definition: NonBlockingHashMapLong.java:390
com.cliffc.aa.util.NonBlockingHashMapLong.clear
void clear(boolean large)
Definition: NonBlockingHashMapLong.java:338
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._vals
final Object[] _vals
Definition: NonBlockingHashMapLong.java:487
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._idx
int _idx
Definition: NonBlockingHashMapLong.java:1051
com.cliffc.aa.util.NonBlockingHashMapLong._Lscale
static final int _Lscale
Definition: NonBlockingHashMapLong.java:107
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.util.ConcurrentAutoTable
An auto-resizing table of.
Definition: ConcurrentAutoTable.java:19
com.cliffc.aa.util.NonBlockingHashMapLong.reprobe_limit
static int reprobe_limit(int len)
Definition: NonBlockingHashMapLong.java:210
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotE._ss
final SnapshotV _ss
Definition: NonBlockingHashMapLong.java:1201
com.cliffc.aa.util.NonBlockingHashMapLong.initialize
void initialize(final int initial_sz)
Definition: NonBlockingHashMapLong.java:242
com.cliffc.aa.util.NonBlockingHashMapLong.clear
void clear()
Removes all of the mappings from this map.
Definition: NonBlockingHashMapLong.java:332
com.cliffc.aa.util.UtilUnsafe
Simple class to obtain access to the Unsafe object.
Definition: UtilUnsafe.java:15
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.removeKey
void removeKey()
Definition: NonBlockingHashMapLong.java:1081
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._copyIdxUpdater
static final AtomicLongFieldUpdater< CHM > _copyIdxUpdater
Definition: NonBlockingHashMapLong.java:847
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._nbhml
final NonBlockingHashMapLong _nbhml
Definition: NonBlockingHashMapLong.java:428
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotE
Definition: NonBlockingHashMapLong.java:1200
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.nextElement
TypeV nextElement()
Definition: NonBlockingHashMapLong.java:1095
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotE.hasNext
boolean hasNext()
Definition: NonBlockingHashMapLong.java:1210
com.cliffc.aa.util.ConcurrentAutoTable.add
void add(long x)
Add the given value to current counter value.
Definition: ConcurrentAutoTable.java:30
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.hasNext
boolean hasNext()
Definition: NonBlockingHashMapLong.java:1054
com.cliffc.aa.util.NonBlockingHashMapLong.size
int size()
Returns the number of key-value mappings in this map.
Definition: NonBlockingHashMapLong.java:255
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.CAS_newchm
boolean CAS_newchm(CHM newchm)
Definition: NonBlockingHashMapLong.java:458
com.cliffc.aa.util.NonBlockingHashMapLong.MATCH_ANY
static final Object MATCH_ANY
Definition: NonBlockingHashMapLong.java:154
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._copyIdx
volatile long _copyIdx
Definition: NonBlockingHashMapLong.java:846
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong
A class which implements the Iterator and Enumeration interfaces, generified to the Long class and su...
Definition: NonBlockingHashMapLong.java:1131
com.cliffc.aa.util.NonBlockingHashMapLong.Prime
Definition: NonBlockingHashMapLong.java:124
com.cliffc.aa.util.NonBlockingHashMapLong.entrySet
Set< Map.Entry< Long, TypeV > > entrySet()
Returns a Set view of the mappings contained in this map.
Definition: NonBlockingHashMapLong.java:1235
AbstractMap
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.SnapshotV
SnapshotV()
Definition: NonBlockingHashMapLong.java:1031
com.cliffc.aa.util.NonBlockingHashMapLong._chm_offset
static final long _chm_offset
Definition: NonBlockingHashMapLong.java:116
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.get_impl
Object get_impl(final long key)
Definition: NonBlockingHashMapLong.java:535
com.cliffc.aa.util.NonBlockingHashMapLong.print_impl
static void print_impl(final int i, final long K, final Object V)
Definition: NonBlockingHashMapLong.java:177
com.cliffc.aa.util.NonBlockingHashMapLong.keySet
Set< Long > keySet()
Returns a Set view of the keys contained in this map; with care the keys may be iterated over without...
Definition: NonBlockingHashMapLong.java:1168
com.cliffc.aa.util.NonBlockingHashMapLong.serialVersionUID
static final long serialVersionUID
Definition: NonBlockingHashMapLong.java:93
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.putIfMatch
Object putIfMatch(final long key, final Object putval, final Object expVal)
Definition: NonBlockingHashMapLong.java:581
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._copyDone
volatile long _copyDone
Definition: NonBlockingHashMapLong.java:853
com.cliffc.aa.util.NonBlockingHashMapLong.Prime.unbox
static Object unbox(Object V)
Definition: NonBlockingHashMapLong.java:127
com.cliffc.aa.util.NonBlockingHashMapLong.get
final TypeV get(long key)
Returns the value to which the specified key is mapped, or.
Definition: NonBlockingHashMapLong.java:368
com.cliffc.aa.util.NonBlockingHashMapLong.NonBlockingHashMapLong
NonBlockingHashMapLong(final boolean opt_for_space)
Create a new NonBlockingHashMapLong, setting the space-for-speed tradeoff.
Definition: NonBlockingHashMapLong.java:232
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.nextElement
Long nextElement()
Auto-box and return the next key.
Definition: NonBlockingHashMapLong.java:1144
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.CAS_key
boolean CAS_key(int idx, long old, long key)
Definition: NonBlockingHashMapLong.java:479
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._prevK
long _prevK
Definition: NonBlockingHashMapLong.java:1052
com.cliffc.aa.util.NonBlockingHashMapLong.NO_KEY
static final long NO_KEY
Definition: NonBlockingHashMapLong.java:167
com.cliffc.aa.util.NonBlockingHashMapLong.put
TypeV put(Long key, TypeV val)
Auto-boxing version of put.
Definition: NonBlockingHashMapLong.java:392
com.cliffc.aa.util.NonBlockingHashMapLong.help_copy
void help_copy()
Definition: NonBlockingHashMapLong.java:403
com.cliffc.aa.util.NonBlockingHashMapLong.putIfAbsent
TypeV putIfAbsent(long key, TypeV val)
Atomically, do a put if-and-only-if the key is not mapped.
Definition: NonBlockingHashMapLong.java:286
com.cliffc.aa.util.NonBlockingHashMapLong.replace
TypeV replace(long key, TypeV val)
Atomically do a put(key,val) if-and-only-if the key is mapped to some value already.
Definition: NonBlockingHashMapLong.java:302
com.cliffc.aa.util.AbstractEntry
A simple implementation of java.util.Map.Entry.
Definition: AbstractEntry.java:15
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._copyDoneUpdater
static final AtomicLongFieldUpdater< CHM > _copyDoneUpdater
Definition: NonBlockingHashMapLong.java:854
com.cliffc.aa.util.NonBlockingHashMapLong.replace
boolean replace(Long key, TypeV oldValue, TypeV newValue)
Auto-boxing version of replace.
Definition: NonBlockingHashMapLong.java:394
com.cliffc.aa.util.NonBlockingHashMapLong.writeObject
void writeObject(java.io.ObjectOutputStream s)
Definition: NonBlockingHashMapLong.java:1256
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._newchm
volatile CHM _newchm
Definition: NonBlockingHashMapLong.java:454
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.IteratorLong
IteratorLong()
A new IteratorLong.
Definition: NonBlockingHashMapLong.java:1134
com.cliffc.aa.util.NonBlockingHashMapLong.readObject
void readObject(java.io.ObjectInputStream s)
Definition: NonBlockingHashMapLong.java:1270
com.cliffc.aa.util.NonBlockingHashMapLong.replace
boolean replace(long key, TypeV oldValue, TypeV newValue)
Atomically do a put(key,newValue) if-and-only-if the key is mapped a value which is equals to oldValu...
Definition: NonBlockingHashMapLong.java:307
com.cliffc.aa.util.UtilUnsafe.UNSAFE
static final Unsafe UNSAFE
Definition: UtilUnsafe.java:17
com.cliffc.aa.util.NonBlockingHashMapLong._opt_for_space
final boolean _opt_for_space
Definition: NonBlockingHashMapLong.java:140
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.resize
CHM resize()
Definition: NonBlockingHashMapLong.java:741
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV
Definition: NonBlockingHashMapLong.java:1029
com.cliffc.aa.util.NonBlockingHashMapLong.Prime._V
final Object _V
Definition: NonBlockingHashMapLong.java:125
com.cliffc.aa.util.NonBlockingHashMapLong.contains
boolean contains(Object val)
Legacy method testing if some key maps into the specified value in this table.
Definition: NonBlockingHashMapLong.java:268
com.cliffc.aa.util.NonBlockingHashMapLong.Prime.Prime
Prime(Object V)
Definition: NonBlockingHashMapLong.java:126
com.cliffc.aa.util.NonBlockingHashMapLong.hash
static final int hash(long h)
Definition: NonBlockingHashMapLong.java:416
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.copy_slot
boolean copy_slot(int idx)
Definition: NonBlockingHashMapLong.java:971
com.cliffc.aa.util.NonBlockingHashMapLong.putIfMatch
TypeV putIfMatch(long key, Object newVal, Object oldVal)
Definition: NonBlockingHashMapLong.java:312
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotE.SnapshotE
SnapshotE()
Definition: NonBlockingHashMapLong.java:1202
com.cliffc.aa.util.NonBlockingHashMapLong.rawIndex
static long rawIndex(final Object[] ary, final int idx)
Definition: NonBlockingHashMapLong.java:100
com.cliffc.aa.util.NonBlockingHashMapLong._Oscale
static final int _Oscale
Definition: NonBlockingHashMapLong.java:99
com.cliffc.aa.util.NonBlockingHashMapLong.MIN_SIZE
static final int MIN_SIZE
Definition: NonBlockingHashMapLong.java:146
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.CHM
CHM(final NonBlockingHashMapLong nbhml, ConcurrentAutoTable size, final int logsize)
Definition: NonBlockingHashMapLong.java:490
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.print2
void print2()
Definition: NonBlockingHashMapLong.java:520
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.key
long key(final int idx)
Definition: NonBlockingHashMapLong.java:1050
com.cliffc.aa.util.UtilUnsafe.fieldOffset
static final long fieldOffset(Class clz, String field)
Definition: UtilUnsafe.java:32
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.util.NonBlockingHashMapLong.containsKey
boolean containsKey(long key)
Tests if the key in the table.
Definition: NonBlockingHashMapLong.java:258
com.cliffc.aa.util.NonBlockingHashMapLong._last_resize_milli
transient long _last_resize_milli
Definition: NonBlockingHashMapLong.java:137
com.cliffc.aa.util.NonBlockingHashMapLong._val_1
transient Object _val_1
Definition: NonBlockingHashMapLong.java:134
com.cliffc.aa.util.NonBlockingHashMapLong.NBHMLEntry
Definition: NonBlockingHashMapLong.java:1192
com.cliffc.aa.util.ConcurrentAutoTable.estimate_get
long estimate_get()
A cheaper get.
Definition: ConcurrentAutoTable.java:60
com.cliffc.aa.util.NonBlockingHashMapLong.TOMBSTONE
static final Object TOMBSTONE
Definition: NonBlockingHashMapLong.java:157
com.cliffc.aa.util.NonBlockingHashMapLong.print2_impl
static void print2_impl(final int i, final long K, final Object V)
Definition: NonBlockingHashMapLong.java:190
com.cliffc.aa.util.NonBlockingHashMapLong._Lbase
static final int _Lbase
Definition: NonBlockingHashMapLong.java:106
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.next
TypeV next()
Definition: NonBlockingHashMapLong.java:1055
com.cliffc.aa.util.NonBlockingHashMapLong.CHM
Definition: NonBlockingHashMapLong.java:426
com.cliffc.aa.util.NonBlockingHashMapLong.clone
NonBlockingHashMapLong< TypeV > clone()
Creates a shallow copy of this hashtable.
Definition: NonBlockingHashMapLong.java:1290
Cloneable
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._keys
final long[] _keys
Definition: NonBlockingHashMapLong.java:486
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.length
int length()
Definition: NonBlockingHashMapLong.java:1049
com.cliffc.aa.util.NonBlockingHashMapLong.containsValue
boolean containsValue(Object val)
Returns true if this Map maps one or more keys to the specified value.
Definition: NonBlockingHashMapLong.java:349
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._resizerUpdater
static final AtomicLongFieldUpdater< CHM > _resizerUpdater
Definition: NonBlockingHashMapLong.java:474
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.DUMMY_VOLATILE
static volatile int DUMMY_VOLATILE
Definition: NonBlockingHashMapLong.java:580
com.cliffc.aa.util.NonBlockingHashMapLong.NO_MATCH_OLD
static final Object NO_MATCH_OLD
Definition: NonBlockingHashMapLong.java:151
com.cliffc.aa.util.AbstractEntry< Long, TypeV >::_val
TypeV _val
Strongly typed value.
Definition: AbstractEntry.java:19
com.cliffc.aa.util.NonBlockingHashMapLong.containsKey
boolean containsKey(Object key)
Auto-boxing version of containsKey(long).
Definition: NonBlockingHashMapLong.java:386
com.cliffc.aa.util.NonBlockingHashMapLong._Obase
static final int _Obase
Definition: NonBlockingHashMapLong.java:98
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.nextLong
long nextLong()
Return the next key as a primitive.
Definition: NonBlockingHashMapLong.java:1140
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._nextK
long _nextK
Definition: NonBlockingHashMapLong.java:1052
com.cliffc.aa.util.AbstractEntry< Long, TypeV >::_key
final TypeK _key
Strongly typed key.
Definition: AbstractEntry.java:17
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._newchmUpdater
static final AtomicReferenceFieldUpdater< CHM, CHM > _newchmUpdater
Definition: NonBlockingHashMapLong.java:455
com.cliffc.aa.util.NonBlockingHashMapLong.reprobes
long reprobes()
Get and clear the current count of reprobes.
Definition: NonBlockingHashMapLong.java:202
com.cliffc.aa.util.NonBlockingHashMapLong
A lock-free alternate implementation of java.util.concurrent.ConcurrentHashMap with primitive long ke...
Definition: NonBlockingHashMapLong.java:91
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.tableFull
boolean tableFull(int reprobe_cnt, int len)
Definition: NonBlockingHashMapLong.java:726
Enumeration
com.cliffc.aa.util.NonBlockingHashMapLong.put
TypeV put(long key, TypeV val)
Maps the specified key to the specified value in the table.
Definition: NonBlockingHashMapLong.java:278
com.cliffc.aa.util.NonBlockingHashMapLong.CHM._resizers
volatile long _resizers
Definition: NonBlockingHashMapLong.java:473
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.copy_check_and_promote
void copy_check_and_promote(int workdone)
Definition: NonBlockingHashMapLong.java:936
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.slots
int slots()
Definition: NonBlockingHashMapLong.java:445
com.cliffc.aa.util.NonBlockingHashMapLong.NonBlockingHashMapLong
NonBlockingHashMapLong(final int initial_sz)
Create a new NonBlockingHashMapLong with initial room for the given number of elements,...
Definition: NonBlockingHashMapLong.java:226
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._nextV
TypeV _nextV
Definition: NonBlockingHashMapLong.java:1053
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotE.next
Map.Entry< Long, TypeV > next()
Definition: NonBlockingHashMapLong.java:1209
com.cliffc.aa.util.NonBlockingHashMapLong.print2
void print2()
Definition: NonBlockingHashMapLong.java:184
com
com.cliffc.aa.util.NonBlockingHashMapLong.NBHMLEntry.setValue
TypeV setValue(final TypeV val)
Definition: NonBlockingHashMapLong.java:1194
com.cliffc.aa.util.ConcurrentAutoTable.get
long get()
Current value of the counter.
Definition: ConcurrentAutoTable.java:50
com.cliffc.aa.util.NonBlockingHashMapLong.TOMBPRIME
static final Prime TOMBPRIME
Definition: NonBlockingHashMapLong.java:162
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV._prevV
TypeV _prevV
Definition: NonBlockingHashMapLong.java:1053
com.cliffc.aa.util.NonBlockingHashMapLong.values
Collection< TypeV > values()
Returns a Collection view of the values contained in this map.
Definition: NonBlockingHashMapLong.java:1118
com.cliffc.aa.util.NonBlockingHashMapLong.SnapshotV.hasMoreElements
boolean hasMoreElements()
Definition: NonBlockingHashMapLong.java:1096
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.hasNext
boolean hasNext()
True if there are more keys to iterate over.
Definition: NonBlockingHashMapLong.java:1142
com.cliffc.aa.util.NonBlockingHashMapLong.CAS
final boolean CAS(final long offset, final Object old, final Object nnn)
Definition: NonBlockingHashMapLong.java:119
com.cliffc.aa.util.NonBlockingHashMapLong.remove
TypeV remove(long key)
Removes the key (and its corresponding value) from this map.
Definition: NonBlockingHashMapLong.java:292
com.cliffc.aa.util.NonBlockingHashMapLong._val_1_offset
static final long _val_1_offset
Definition: NonBlockingHashMapLong.java:117
com.cliffc.aa.util.NonBlockingHashMapLong.NonBlockingHashMapLong
NonBlockingHashMapLong(final int initial_sz, final boolean opt_for_space)
Create a new NonBlockingHashMapLong, setting both the initial size and the space-for-speed tradeoff.
Definition: NonBlockingHashMapLong.java:238
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.CAS_val
boolean CAS_val(int idx, Object old, Object val)
Definition: NonBlockingHashMapLong.java:482
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.next
Long next()
Auto-box and return the next key.
Definition: NonBlockingHashMapLong.java:1138
com.cliffc.aa.util.NonBlockingHashMapLong.IteratorLong.hasMoreElements
boolean hasMoreElements()
True if there are more keys to iterate over.
Definition: NonBlockingHashMapLong.java:1146
com.cliffc.aa.util.NonBlockingHashMapLong.CHM.print
void print()
Definition: NonBlockingHashMapLong.java:506