private static boolean compareAndSetState( long address, long expect, long update ) { return UnsafeUtil.compareAndSwapLong( null, address, expect, update ); }
private void increaseFileSizeTo( long newFileSize ) { long currentFileSize; do { currentFileSize = getCurrentFileSize(); } while ( currentFileSize < newFileSize && !UnsafeUtil.compareAndSwapLong( this, fileSizeOffset, currentFileSize, newFileSize ) ); }
private void doUnlock( long targetLockBit ) { long currentState; long newState; do { currentState = state; if ( !canUnlock( currentState, targetLockBit) ) { throw new IllegalStateException( "Can not unlock lock that is already locked" ); } newState = currentState & ~targetLockBit; } while ( !UnsafeUtil.compareAndSwapLong( this, stateOffset, currentState, newState ) ); }
/** * Atomically set field or array element to a maximum between current value and provided <code>newValue</code> */ public static void compareAndSetMaxLong( Object object, long fieldOffset, long newValue ) { long currentValue; do { currentValue = UnsafeUtil.getLongVolatile( object, fieldOffset ); if ( currentValue >= newValue ) { return; } } while ( !UnsafeUtil.compareAndSwapLong( object, fieldOffset, currentValue, newValue ) ); }
/** * Make sure that the lastPageId is at least the given pageId */ void increaseLastPageIdTo( long newLastPageId ) { long current; long update; long lastPageId; do { current = getHeaderState(); update = newLastPageId + (current & headerStateRefCountMask); lastPageId = current & headerStateLastPageIdMask; } while ( lastPageId < newLastPageId && !UnsafeUtil.compareAndSwapLong( this, headerStateOffset, current, update ) ); }
private void doLock( long targetLockBit ) { long currentState; long newState; do { currentState = state; while ( !canLock( currentState, targetLockBit ) ) { // sleep sleep(); currentState = state; } newState = currentState | targetLockBit; } while ( !UnsafeUtil.compareAndSwapLong( this, stateOffset, currentState, newState ) ); }
/** * Decrement the usage stamp. Returns true if it reaches 0. **/ boolean decrementUsage( long pageRef ) { // This is intentionally left benignly racy for performance. long address = offPageBinding( pageRef ); long value = UnsafeUtil.getLongVolatile( address ); long usage = value & MASK_USAGE_COUNT; if ( usage > 0 ) { long update = value - 1; // See `incrementUsage` about why we use `compareAndSwapLong`. UnsafeUtil.compareAndSwapLong( null, address, value, update ); } return usage <= 1; }
/** * Atomically decrement the reference count. Returns true if this was the * last reference. */ boolean decrementRefCount() { long current; long update; long count; do { current = getHeaderState(); count = refCountOf( current ) - 1; if ( count < 0 ) { throw new IllegalStateException( "File has already been closed and unmapped. " + "It cannot be closed any further." ); } update = (current & headerStateLastPageIdMask) + (count << headerStateRefCountShift); } while ( !UnsafeUtil.compareAndSwapLong( this, headerStateOffset, current, update ) ); return count == 0; }
/** * Increment the usage stamp to at most 4. **/ void incrementUsage( long pageRef ) { // This is intentionally left benignly racy for performance. long address = offPageBinding( pageRef ); long value = UnsafeUtil.getLongVolatile( address ); long usage = value & MASK_USAGE_COUNT; if ( usage < MAX_USAGE_COUNT ) // avoid cache sloshing by not doing a write if counter is already maxed out { long update = value + 1; // Use compareAndSwapLong to only actually store the updated count if nothing else changed // in this word-line. The word-line is shared with the file page id, and the swapper id. // Those fields are updated under guard of the exclusive lock, but we *might* race with // that here, and in that case we would never want a usage counter update to clobber a page // binding update. UnsafeUtil.compareAndSwapLong( null, address, value, update ); } }
/** * Atomically increment the reference count for this mapped file. */ void incrementRefCount() { long current; long update; do { current = getHeaderState(); long count = refCountOf( current ) + 1; if ( count > headerStateRefCountMax ) { throw new IllegalStateException( "Cannot map file because reference counter would overflow. " + "Maximum reference count is " + headerStateRefCountMax + ". " + "File is " + swapper.file().getAbsolutePath() ); } update = (current & headerStateLastPageIdMask) + (count << headerStateRefCountShift); } while ( !UnsafeUtil.compareAndSwapLong( this, headerStateOffset, current, update ) ); }
@Test void compareAndSwapLongField() { Obj obj = new Obj(); long aLongOffset = getFieldOffset( Obj.class, "aLong" ); assertTrue( compareAndSwapLong( obj, aLongOffset, 0, 5 ) ); assertFalse( compareAndSwapLong( obj, aLongOffset, 0, 5 ) ); assertTrue( compareAndSwapLong( obj, aLongOffset, 5, 0 ) ); assertThat( obj, is( new Obj() ) ); }
private static boolean compareAndSetState( long address, long expect, long update ) { return UnsafeUtil.compareAndSwapLong( null, address, expect, update ); }
private void increaseFileSizeTo( long newFileSize ) { long currentFileSize; do { currentFileSize = getCurrentFileSize(); } while ( currentFileSize < newFileSize && !UnsafeUtil.compareAndSwapLong( this, fileSizeOffset, currentFileSize, newFileSize ) ); }
private void doUnlock( long targetLockBit ) { long currentState; long newState; do { currentState = state; if ( !canUnlock( currentState, targetLockBit) ) { throw new IllegalStateException( "Can not unlock lock that is already locked" ); } newState = currentState & ~targetLockBit; } while ( !UnsafeUtil.compareAndSwapLong( this, stateOffset, currentState, newState ) ); }
/** * Atomically set field or array element to a maximum between current value and provided <code>newValue</code> */ public static void compareAndSetMaxLong( Object object, long fieldOffset, long newValue ) { long currentValue; do { currentValue = UnsafeUtil.getLongVolatile( object, fieldOffset ); if ( currentValue >= newValue ) { return; } } while ( !UnsafeUtil.compareAndSwapLong( object, fieldOffset, currentValue, newValue ) ); }
/** * Make sure that the lastPageId is at least the given pageId */ void increaseLastPageIdTo( long newLastPageId ) { long current; long update; long lastPageId; do { current = getHeaderState(); update = newLastPageId + (current & headerStateRefCountMask); lastPageId = current & headerStateLastPageIdMask; } while ( lastPageId < newLastPageId && !UnsafeUtil.compareAndSwapLong( this, headerStateOffset, current, update ) ); }
private void doLock( long targetLockBit ) { long currentState; long newState; do { currentState = state; while ( !canLock( currentState, targetLockBit ) ) { // sleep sleep(); currentState = state; } newState = currentState | targetLockBit; } while ( !UnsafeUtil.compareAndSwapLong( this, stateOffset, currentState, newState ) ); }
/** * Decrement the usage stamp. Returns true if it reaches 0. **/ boolean decrementUsage( long pageRef ) { // This is intentionally left benignly racy for performance. long address = offPageBinding( pageRef ); long value = UnsafeUtil.getLongVolatile( address ); long usage = value & MASK_USAGE_COUNT; if ( usage > 0 ) { long update = value - 1; // See `incrementUsage` about why we use `compareAndSwapLong`. UnsafeUtil.compareAndSwapLong( null, address, value, update ); } return usage <= 1; }
/** * Increment the usage stamp to at most 4. **/ void incrementUsage( long pageRef ) { // This is intentionally left benignly racy for performance. long address = offPageBinding( pageRef ); long value = UnsafeUtil.getLongVolatile( address ); long usage = value & MASK_USAGE_COUNT; if ( usage < MAX_USAGE_COUNT ) // avoid cache sloshing by not doing a write if counter is already maxed out { long update = value + 1; // Use compareAndSwapLong to only actually store the updated count if nothing else changed // in this word-line. The word-line is shared with the file page id, and the swapper id. // Those fields are updated under guard of the exclusive lock, but we *might* race with // that here, and in that case we would never want a usage counter update to clobber a page // binding update. UnsafeUtil.compareAndSwapLong( null, address, value, update ); } }
/** * Atomically increment the reference count for this mapped file. */ void incrementRefCount() { long current; long update; do { current = getHeaderState(); long count = refCountOf( current ) + 1; if ( count > headerStateRefCountMax ) { throw new IllegalStateException( "Cannot map file because reference counter would overflow. " + "Maximum reference count is " + headerStateRefCountMax + ". " + "File is " + swapper.file().getAbsolutePath() ); } update = (current & headerStateLastPageIdMask) + (count << headerStateRefCountShift); } while ( !UnsafeUtil.compareAndSwapLong( this, headerStateOffset, current, update ) ); }