@Override public boolean reEnterShared( ResourceType resourceType, long resourceId ) { stateHolder.incrementActiveClients( this ); try { return reEnter( localShared( resourceType ), resourceId ); } finally { stateHolder.decrementActiveClients(); } }
@Test public void shouldBeAbleToResetAndReuseClientState() { // given LockClientStateHolder lockClientStateHolder = new LockClientStateHolder(); // when lockClientStateHolder.incrementActiveClients( new NoOpClient() ); lockClientStateHolder.incrementActiveClients( new NoOpClient() ); lockClientStateHolder.decrementActiveClients(); // expect assertTrue(lockClientStateHolder.hasActiveClients()); // and when lockClientStateHolder.stopClient(); // expect assertTrue( lockClientStateHolder.hasActiveClients() ); assertTrue( lockClientStateHolder.isStopped() ); // and when lockClientStateHolder.reset(); // expect assertFalse( lockClientStateHolder.hasActiveClients() ); assertFalse( lockClientStateHolder.isStopped() ); // when lockClientStateHolder.incrementActiveClients( new NoOpClient() ); assertTrue( lockClientStateHolder.hasActiveClients() ); assertFalse( lockClientStateHolder.isStopped() ); }
@Override public void close() { stateHolder.closeClient(); terminateAllWaitersAndWaitForClientsToLeave(); releaseLocks(); }
/** * Move the client to the PREPARE state, unless it is already STOPPED. */ public void prepare( Locks.Client client ) { int currentValue; int newValue; do { currentValue = clientState.get(); if ( isStopped( currentValue ) ) { throw new LockClientStoppedException( client ); } newValue = stateWithNewStatus( currentValue, PREPARE ); } while ( !clientState.compareAndSet( currentValue, newValue ) ); }
/** * Increment active number of clients that use current state instance. * * @param client the locks client associated with this state; used only to create pretty exception * with {@link LockClientStoppedException#LockClientStoppedException(Locks.Client)}. * @throws LockClientStoppedException when stopped. */ public void incrementActiveClients( Locks.Client client ) { int currentState; do { currentState = clientState.get(); if ( isStopped( currentState ) ) { throw new LockClientStoppedException( client ); } } while ( !clientState.compareAndSet( currentState, incrementActiveClients( currentState ) ) ); }
@Test public void shouldAllowIncrementDecrementClientsWhileNotClosed() { // given LockClientStateHolder lockClientStateHolder = new LockClientStateHolder(); // expect assertFalse( lockClientStateHolder.hasActiveClients() ); lockClientStateHolder.incrementActiveClients( new NoOpClient() ); assertTrue( lockClientStateHolder.hasActiveClients() ); lockClientStateHolder.incrementActiveClients( new NoOpClient() ); lockClientStateHolder.incrementActiveClients( new NoOpClient() ); lockClientStateHolder.decrementActiveClients(); lockClientStateHolder.decrementActiveClients(); lockClientStateHolder.decrementActiveClients(); assertFalse( lockClientStateHolder.hasActiveClients() ); }
@Override public void stop() { // closing client to prevent any new client to come if ( stateHolder.stopClient() ) { // wake up and terminate waiters terminateAllWaitersAndWaitForClientsToLeave(); releaseLocks(); } }
private void terminateAllWaitersAndWaitForClientsToLeave() { terminateAllWaiters(); // wait for all active clients to go and terminate latecomers while ( stateHolder.hasActiveClients() ) { terminateAllWaiters(); LockSupport.parkNanos( TimeUnit.MILLISECONDS.toNanos( 20 ) ); } }
/** * Check if stopped * * @return true if client is stopped, false otherwise */ public boolean isStopped() { return isStopped( clientState.get() ); }
/** * Decrement number of active clients that use current client state object. */ public void decrementActiveClients() { int currentState; do { currentState = clientState.get(); } while ( !clientState.compareAndSet( currentState, decrementActiveClients( currentState ) ) ); }
@Override public void prepare() { stateHolder.prepare( this ); }
/** * Reset current client state. Make it ready for next bunch of operations. * Should be used before factory release client to public usage. */ public void reset() { stateHolder.reset(); }
@Test public void shouldBeAbleToDecrementActiveItemAndDetectWhenFree() { // given LockClientStateHolder lockClientStateHolder = new LockClientStateHolder(); // when lockClientStateHolder.incrementActiveClients(new NoOpClient()); lockClientStateHolder.incrementActiveClients(new NoOpClient()); lockClientStateHolder.decrementActiveClients(); lockClientStateHolder.incrementActiveClients(new NoOpClient()); // expect assertTrue( lockClientStateHolder.hasActiveClients() ); // and when lockClientStateHolder.stopClient(); // expect assertTrue( lockClientStateHolder.hasActiveClients() ); lockClientStateHolder.decrementActiveClients(); assertTrue( lockClientStateHolder.hasActiveClients() ); lockClientStateHolder.decrementActiveClients(); assertFalse( lockClientStateHolder.hasActiveClients() ); }
/** * Increment active number of clients that use current state instance. * * @param client the locks client associated with this state; used only to create pretty exception * with {@link LockClientStoppedException#LockClientStoppedException(Locks.Client)}. * @throws LockClientStoppedException when stopped. */ public void incrementActiveClients( Locks.Client client ) { int currentState; do { currentState = clientState.get(); if ( isStopped( currentState ) ) { throw new LockClientStoppedException( client ); } } while ( !clientState.compareAndSet( currentState, incrementActiveClients( currentState ) ) ); }
/** * Move the client to the PREPARE state, unless it is already STOPPED. */ public void prepare( Locks.Client client ) { int currentValue; int newValue; do { currentValue = clientState.get(); if ( isStopped( currentValue ) ) { throw new LockClientStoppedException( client ); } newValue = stateWithNewStatus( currentValue, PREPARE ); } while ( !clientState.compareAndSet( currentValue, newValue ) ); }
@Override public void stop() { // closing client to prevent any new client to come if ( stateHolder.stopClient() ) { // wake up and terminate waiters terminateAllWaitersAndWaitForClientsToLeave(); releaseLocks(); } }
private void waitForAllClientsToLeave() { while ( stateHolder.hasActiveClients() ) { try { Thread.sleep( 10 ); } catch ( InterruptedException e ) { Thread.interrupted(); } } }
/** * Check if stopped * * @return true if client is stopped, false otherwise */ public boolean isStopped() { return isStopped( clientState.get() ); }
/** * Decrement number of active clients that use current client state object. */ public void decrementActiveClients() { int currentState; do { currentState = clientState.get(); } while ( !clientState.compareAndSet( currentState, decrementActiveClients( currentState ) ) ); }
@Override public void prepare() { stateHolder.prepare( this ); }