/** * Try to acquire a lock, failing with an exception otherwise. */ private void lock(LeaseLock lock) throws Exception { final LeaseLock.AcquireResult acquireResult = lock.tryAcquire(this.lockAcquisitionTimeoutMillis, this.pauser, () -> !this.interrupted); switch (acquireResult) { case Timeout: throw new Exception("timed out waiting for lock"); case Exit: this.interrupted = false; throw new InterruptedException("LeaseLock was interrupted"); case Done: break; default: throw new AssertionError(acquireResult + " not managed"); } }
/** * Not reentrant lock acquisition operation (ie {@link #tryAcquire()}). * It tries to acquire the lock until will succeed (ie {@link AcquireResult#Done}), got interrupted (ie {@link AcquireResult#Exit}) * or exceed {@code tryAcquireTimeoutMillis}. * After each failed attempt is performed a {@link Pauser#idle} call. * If the specified timeout is <=0 then it behaves as {@link #tryAcquire(ExitCondition, Pauser)}. */ default AcquireResult tryAcquire(long tryAcquireTimeoutMillis, Pauser pauser, ExitCondition exitCondition) { if (tryAcquireTimeoutMillis < 0) { return tryAcquire(exitCondition, pauser); } final long timeoutInNanosecond = TimeUnit.MILLISECONDS.toNanos(tryAcquireTimeoutMillis); final long startAcquire = System.nanoTime(); while (exitCondition.keepRunning()) { if (tryAcquire()) { return AcquireResult.Done; } else if (System.nanoTime() - startAcquire >= timeoutInNanosecond) { return AcquireResult.Timeout; } else { pauser.idle(); //check before doing anything if time is expired if (System.nanoTime() - startAcquire >= timeoutInNanosecond) { return AcquireResult.Timeout; } } } return AcquireResult.Exit; }
/** * Not reentrant lock acquisition operation (ie {@link #tryAcquire()}). * It tries to acquire the lock until will succeed (ie {@link AcquireResult#Done})or got interrupted (ie {@link AcquireResult#Exit}). * After each failed attempt is performed a {@link Pauser#idle} call. */ default AcquireResult tryAcquire(ExitCondition exitCondition, Pauser pauser) { while (exitCondition.keepRunning()) { if (tryAcquire()) { return AcquireResult.Done; } else { pauser.idle(); } } return AcquireResult.Exit; }
@Test public void shouldNotAcquireLockTwice() { final LeaseLock lock = lock(); Assert.assertTrue("Must acquire the lock", lock.tryAcquire()); try { Assert.assertFalse("lock already acquired", lock.tryAcquire()); } finally { lock.release(); } }
try { for (int i = 0; i < writesPerProducer; i++) { final LeaseLock.AcquireResult acquireResult = lock.tryAcquire(millisToAcquireLock, pauser, () -> true); if (acquireResult != LeaseLock.AcquireResult.Done) { throw new IllegalStateException(acquireResult + " from " + Thread.currentThread());
@Test public void shouldAcquireExpiredLock() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); try { Thread.sleep(lock.expirationMillis() * 2); Assert.assertFalse("lock is already expired", lock.isHeldByCaller()); Assert.assertFalse("lock is already expired", lock.isHeld()); Assert.assertTrue("lock is already expired", lock.tryAcquire()); } finally { lock.release(); } }
@Test public void shouldRenewAcquiredLock() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(10)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); try { Assert.assertTrue("lock is owned", lock.renew()); } finally { lock.release(); } }
@Test public void shouldOtherAcquireExpiredLock() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); try { Thread.sleep(lock.expirationMillis() * 2); Assert.assertFalse("lock is already expired", lock.isHeldByCaller()); Assert.assertFalse("lock is already expired", lock.isHeld()); final LeaseLock otherLock = lock(TimeUnit.SECONDS.toMillis(10)); try { Assert.assertTrue("lock is already expired", otherLock.tryAcquire()); } finally { otherLock.release(); } } finally { lock.release(); } }
@Test public void shouldAcquireLock() { final LeaseLock lock = lock(); final boolean acquired = lock.tryAcquire(); Assert.assertTrue("Must acquire the lock!", acquired); try { Assert.assertTrue("The lock is been held by the caller!", lock.isHeldByCaller()); } finally { lock.release(); } }
@Test public void shouldNotRenewLockAcquiredByOthers() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); try { Thread.sleep(lock.expirationMillis() * 2); Assert.assertFalse("lock is already expired", lock.isHeldByCaller()); Assert.assertFalse("lock is already expired", lock.isHeld()); final LeaseLock otherLock = lock(TimeUnit.SECONDS.toMillis(10)); Assert.assertTrue("lock is already expired", otherLock.tryAcquire()); try { Assert.assertFalse("lock is owned by others", lock.renew()); } finally { otherLock.release(); } } finally { lock.release(); } } }
@Test public void shouldNotAcquireLockWhenAlreadyHeldByOthers() { final LeaseLock lock = lock(); Assert.assertTrue("Must acquire the lock", lock.tryAcquire()); try { Assert.assertTrue("Lock held by the caller", lock.isHeldByCaller()); final LeaseLock failingLock = lock(); Assert.assertFalse("lock already held by other", failingLock.tryAcquire()); Assert.assertFalse("lock already held by other", failingLock.isHeldByCaller()); Assert.assertTrue("lock already held by other", failingLock.isHeld()); } finally { lock.release(); } }
@Test public void shouldRenewExpiredLockNotAcquiredByOthers() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); try { Thread.sleep(lock.expirationMillis() * 2); Assert.assertFalse("lock is already expired", lock.isHeldByCaller()); Assert.assertFalse("lock is already expired", lock.isHeld()); Assert.assertTrue("lock is owned", lock.renew()); } finally { lock.release(); } }
@Test public void shouldNotRenewReleasedLock() throws InterruptedException { final LeaseLock lock = lock(TimeUnit.SECONDS.toMillis(10)); Assert.assertTrue("lock is not owned by anyone", lock.tryAcquire()); lock.release(); Assert.assertFalse("lock is already released", lock.isHeldByCaller()); Assert.assertFalse("lock is already released", lock.isHeld()); Assert.assertFalse("lock is already released", lock.renew()); }