package de.axone.thread;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
public class ThreadsafeContractor {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ReadLock READlock = lock.readLock();
private final WriteLock WRITElock = lock.writeLock();
public <T extends Throwable> Executor when( Condition condition ) throws T{
READlock.lock();
try {
if( condition.test() ){
return new ExecutorImpl( condition );
} else {
return new NoExecutorImpl();
}
} finally { READlock.unlock(); }
}
public interface Executor {
public <T extends Throwable> void then( Operation<T> operation ) throws T;
}
private class ExecutorImpl implements Executor {
final Condition test;
ExecutorImpl( Condition test ){
this.test = test;
}
@Override
public <T extends Throwable> void then( Operation<T> operation ) throws T {
WRITElock.lock();
try {
// Retest if the condition was fullfilled in the meantime
if( test.test() ) {
operation.run();
}
} finally { WRITElock.unlock(); }
}
}
private class NoExecutorImpl implements Executor {
@Override
public <T extends Throwable> void then( Operation<T> op ) throws T {
//NOP
}
}
@FunctionalInterface
public interface Condition {
public boolean test();
}
@FunctionalInterface
public interface Operation<T extends Throwable> {
public void run() throws T;
}
}