private final void help_copy_impl( NonBlockingHashMap topmap, Object[] oldkvs, boolean copy_all ) {
      assert chm(oldkvs) == this;
      Object[] newkvs = _newkvs;
      assert newkvs != null;    // Already checked by caller
      int oldlen = len(oldkvs); // Total amount to copy
      final int MIN_COPY_WORK = Math.min(oldlen,1024); // Limit per-thread work

      // ---
      int panic_start = -1;
      int copyidx=-9999;            // Fool javac to think it's initialized
      while( _copyDone < oldlen ) { // Still needing to copy?
        // Carve out a chunk of work.  The counter wraps around so every
        // thread eventually tries to copy every slot repeatedly.

        // We "panic" if we have tried TWICE to copy every slot - and it still
        // has not happened.  i.e., twice some thread somewhere claimed they
        // would copy 'slot X' (by bumping _copyIdx) but they never claimed to
        // have finished (by bumping _copyDone).  Our choices become limited:
        // we can wait for the work-claimers to finish (and become a blocking
        // algorithm) or do the copy work ourselves.  Tiny tables with huge
        // thread counts trying to copy the table often 'panic'.
        if( panic_start == -1 ) { // No panic?
          copyidx = (int)_copyIdx;
          while( !_copyIdxUpdater.compareAndSet(this,copyidx,copyidx+MIN_COPY_WORK) )
            copyidx = (int)_copyIdx;      // Re-read
          if( !(copyidx < (oldlen<<1)) )  // Panic!
            panic_start = copyidx;        // Record where we started to panic-copy
        }

        // We now know what to copy.  Try to copy.
        int workdone = 0;
        for( int i=0; i<MIN_COPY_WORK; i++ )
          if( copy_slot(topmap,(copyidx+i)&(oldlen-1),oldkvs,newkvs) ) // Made an oldtable slot go dead?
            workdone++;         // Yes!
        if( workdone > 0 )      // Report work-done occasionally
          copy_check_and_promote( topmap, oldkvs, workdone );// See if we can promote
        //for( int i=0; i<MIN_COPY_WORK; i++ )
        //  if( copy_slot(topmap,(copyidx+i)&(oldlen-1),oldkvs,newkvs) ) // Made an oldtable slot go dead?
        //    copy_check_and_promote( topmap, oldkvs, 1 );// See if we can promote

        copyidx += MIN_COPY_WORK;
        // Uncomment these next 2 lines to turn on incremental table-copy.
        // Otherwise this thread continues to copy until it is all done.
        if( !copy_all && panic_start == -1 ) // No panic?
          return;       // Then done copying after doing MIN_COPY_WORK
      }
      // Extra promotion check, in case another thread finished all copying
      // then got stalled before promoting.
      copy_check_and_promote( topmap, oldkvs, 0 );// See if we can promote
    }
Put, Remove, PutIfAbsent, etc.  Return the old value.  If the returned value is equal to expVal (or expVal is
{@link #NO_MATCH_OLD}) then the put can be assumed to work (although might have been immediately overwritten).
Only the path through copy_slot passes in an expected value of null, and putIfMatch only returns a null if passed
in an expected null.

@param topmap the map to act on
@param kvs the KV table snapshot we act on
@param key not null (will result in {@link NullPointerException})
@param putval the new value to use. Not null. {@link #TOMBSTONE} will result in deleting the entry.
@param expVal expected old value. Can be null. {@link #NO_MATCH_OLD} for an unconditional put/remove.
             {@link #TOMBSTONE} if we expect old entry to not exist(null/{@link #TOMBSTONE} value).
             {@link #MATCH_ANY} will ignore the current value, but only if an entry exists. A null expVal is used
              internally to perform a strict insert-if-never-been-seen-before operation.
@return {@link #TOMBSTONE} if key does not exist or match has failed. null if expVal is
null AND old value was null. Otherwise the old entry value (not null).
jctools-core/src/main/java/org/jctools/maps/NonBlockingHashMap.java