StorageManager supports centralized exception handling
This commit is contained in:
@@ -31,7 +31,27 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LockBasedStorageManager implements StorageManager {
|
||||
|
||||
public static final StorageManager NO_LOCKS = new LockBasedStorageManager("NO_LOCKS", NoLock.INSTANCE) {
|
||||
public interface ExceptionHandlingStrategy {
|
||||
ExceptionHandlingStrategy THROW = new ExceptionHandlingStrategy() {
|
||||
@NotNull
|
||||
@Override
|
||||
public RuntimeException handleException(@NotNull Throwable throwable) {
|
||||
throw ExceptionUtils.rethrow(throwable);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The signature of this method is a trick: it is used as
|
||||
*
|
||||
* throw strategy.handleException(...)
|
||||
*
|
||||
* most implementations of this method throw exceptions themselves, so it does not matter what they return
|
||||
*/
|
||||
@NotNull
|
||||
RuntimeException handleException(@NotNull Throwable throwable);
|
||||
}
|
||||
|
||||
public static final StorageManager NO_LOCKS = new LockBasedStorageManager("NO_LOCKS", ExceptionHandlingStrategy.THROW, NoLock.INSTANCE) {
|
||||
@NotNull
|
||||
@Override
|
||||
protected <T> RecursionDetectedResult<T> recursionDetectedDefault() {
|
||||
@@ -39,16 +59,30 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
}
|
||||
};
|
||||
|
||||
public static LockBasedStorageManager createWithExceptionHandling(@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy) {
|
||||
return new LockBasedStorageManager(exceptionHandlingStrategy);
|
||||
}
|
||||
|
||||
protected final Lock lock;
|
||||
private final ExceptionHandlingStrategy exceptionHandlingStrategy;
|
||||
private final String debugText;
|
||||
|
||||
private LockBasedStorageManager(@NotNull String debugText, @NotNull Lock lock) {
|
||||
private LockBasedStorageManager(
|
||||
@NotNull String debugText,
|
||||
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy,
|
||||
@NotNull Lock lock
|
||||
) {
|
||||
this.lock = lock;
|
||||
this.exceptionHandlingStrategy = exceptionHandlingStrategy;
|
||||
this.debugText = debugText;
|
||||
}
|
||||
|
||||
public LockBasedStorageManager() {
|
||||
this(getPointOfConstruction(), new ReentrantLock());
|
||||
this(getPointOfConstruction(), ExceptionHandlingStrategy.THROW, new ReentrantLock());
|
||||
}
|
||||
|
||||
private LockBasedStorageManager(@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy) {
|
||||
this(getPointOfConstruction(), exceptionHandlingStrategy, new ReentrantLock());
|
||||
}
|
||||
|
||||
private static String getPointOfConstruction() {
|
||||
@@ -276,7 +310,7 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
// Store only if it's a genuine result, not something thrown through recursionDetected()
|
||||
value = WrappedValues.escapeThrowable(throwable);
|
||||
}
|
||||
throw ExceptionUtils.rethrow(throwable);
|
||||
throw exceptionHandlingStrategy.handleException(throwable);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -352,12 +386,12 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
return typedValue;
|
||||
}
|
||||
catch (Throwable throwable) {
|
||||
if (throwable == error) throw error;
|
||||
if (throwable == error) throw exceptionHandlingStrategy.handleException(throwable);
|
||||
|
||||
Object oldValue = cache.put(input, WrappedValues.escapeThrowable(throwable));
|
||||
assert oldValue == NotValue.COMPUTING : "Race condition detected on input " + input + ". Old value is " + oldValue;
|
||||
|
||||
throw ExceptionUtils.rethrow(throwable);
|
||||
throw exceptionHandlingStrategy.handleException(throwable);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
||||
Reference in New Issue
Block a user