Futures lockAndInvalidate( H2ONode sender, Value newval, Futures fs ) {
    assert _key.home(); // Only the HOME node for a key tracks replicas
    assert newval._rwlock.get() >= 1; // starts read-locked
    // Write-Lock against further GETs
    while( true ) {      // Repeat, in case racing GETs are bumping the counter
      int old = _rwlock.get();
      assert old >= 0 : _key+", rwlock="+old;  // Count does not go negative
      assert old != -1; // Only the thread doing a PUT ever locks
      if( old !=0 ) { // has readers?
        // Active readers: need to block until the GETs (of this very Value!)
        // all complete, before we can invalidate this Value - lest a racing
        // Invalidate bypass a GET.
        try { ForkJoinPool.managedBlock(this); } catch( InterruptedException ignore ) { }
      } else if( RW_CAS(0,-1,"wlock") )
        break;                  // Got the write-lock!
    }
    // We have the set of Nodes with replicas now.  Ship out invalidates.
    // Bump the newval read-lock by 1 for each pending invalidate
    byte[] r = _replicas;
    if( r!=null ) { // No replicas, nothing to invalidate
      int max = r.length;
      for( int i=0; i<max; i++ )
        if( r[i]==1 && H2ONode.IDX[i] != sender )
          TaskInvalidateKey.invalidate(H2ONode.IDX[i],_key,newval,fs);
    }
    newval.lowerActiveGetCount(null);  // Remove initial read-lock, accounting for pending inv counts
    return fs;
  }
Futures lockAndInvalidate ( H2ONode sender , Value newval , Futures fs ) { assert _key . home ( ) ; assert newval . _rwlock . get ( ) >= 1 ; while ( true ) { int old = _rwlock . get ( ) ; assert old >= 0 : _key + ", rwlock=" + old ; assert old != - 1 ; if ( old != 0 ) { try { ForkJoinPool . managedBlock ( this ) ; } catch ( InterruptedException ignore ) { } } else if ( RW_CAS ( 0 , - 1 , "wlock" ) ) break ; } byte [ ] r = _replicas ; if ( r != null ) { int max = r . length ; for ( int i = 0 ; i < max ; i ++ ) if ( r [ i ] == 1 && H2ONode . IDX [ i ] != sender ) TaskInvalidateKey . invalidate ( H2ONode . IDX [ i ] , _key , newval , fs ) ; } newval . lowerActiveGetCount ( null ) ; return fs ; }
This value was atomically extracted from the local STORE by a successful
TaskPutKey attempt (only 1 thread can ever extract and thus call here).
No future lookups will find this Value, but there may be existing uses.
Atomically set the rwlock count to -1 locking it from further GETs and
ship out invalidates to caching replicas.  May need to block on active
GETs.  Updates a set of Future invalidates that can be blocked against.