Make sure lock is free'd even on error (fixes #3116)

This commit is contained in:
SirYwell 2021-08-23 10:05:38 +02:00
parent a8fc6662e0
commit 6ec136a03d
2 changed files with 43 additions and 5 deletions

View File

@ -71,11 +71,9 @@ public final class LockRepository {
* @param runnable Action to run when the lock is available
*/
public void useLock(final @NonNull LockKey key, final @NonNull Runnable runnable) {
this.useLock(key, lock -> {
lock.lock();
runnable.run();
lock.unlock();
});
try (LockAccess ignored = lock(key)) {
runnable.run();
}
}
/**

View File

@ -0,0 +1,40 @@
package com.plotsquared.core.synchronization;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
class LockRepositoryTest {
private LockKey key;
private LockRepository lockRepository;
@BeforeEach
void setUp() {
this.key = LockKey.of("test");
this.lockRepository = new LockRepository();
}
@Test
@DisplayName("Unlock even if there is an error")
void useLockUnlock() {
Lock l = this.lockRepository.getLock(this.key);
// Striped uses a ReentrantLock internally, and we need its isLocked method for this test
if (!(l instanceof ReentrantLock lock)) {
throw new IllegalStateException("Expected a ReentrantLock");
}
assertThrows(IllegalStateException.class, () -> {
this.lockRepository.useLock(this.key, () -> {
throw new IllegalStateException();
});
});
assertFalse(lock.isLocked());
}
}