import org.simantics.db.impl.query.PendingTaskSupport;
import org.simantics.db.procedure.AsyncProcedure;
import org.simantics.db.request.AsyncRead;
-public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
+
+public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result>, Runnable {
private static final Object NO_RESULT = new Object();
private final Object key;
private final ReadGraphImpl queryGraph;
private final ReadGraphImpl callerGraph;
+ private final AsyncReadEntry<Result> entry;
private final AsyncProcedure<Result> procedure;
private PendingTaskSupport pendingTaskSupport;
private final boolean needsToBlock;
private Object result = NO_RESULT;
private Throwable exception = null;
-
- private ReadGraphImpl queryGraph() {
- return queryGraph;
- }
public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure, Object key, boolean needsToBlock) {
// A new graph for evaluating the query with correct parent and asyncBarrier
- queryGraph = callerGraph.withParent(entry, () -> {
-
- dispatchProcedure(queryGraph(), callerGraph, entry, procedure, needsToBlock);
-
- }, needsToBlock);
-
+ queryGraph = callerGraph.withParent(entry, this, needsToBlock);
queryGraph.asyncBarrier.inc();
+
+ // This makes sure that caller does not quit before dispatch
+ callerGraph.asyncBarrier.inc();
+ this.entry = entry;
this.procedure = procedure;
this.key = key;
this.queryGraph.asyncBarrier.inc();
return "." + procedure;
}
- private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure_, boolean needsToBlock) {
+ @Override
+ public void run() {
- AsyncProcedure<Result> procedure = entry != null ? entry : procedure_;
+ AsyncProcedure<Result> procedure__ = entry != null ? entry : procedure;
- ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent, null, needsToBlock);
+ ReadGraphImpl executeGraph = callerGraph.withParent(callerGraph.parent, null, needsToBlock);
executeGraph.asyncBarrier.inc();
+
+ // This counters the inc in the constructor
+ callerGraph.asyncBarrier.dec();
+
try {
- if(procedure != null) {
- procedure.execute(executeGraph, get());
+ if(procedure__ != null) {
+ procedure__.execute(executeGraph, get());
}
} catch (DatabaseException e) {
- if(procedure != null) procedure.exception(executeGraph, e);
+ if(procedure__ != null) procedure__.exception(executeGraph, e);
exception = e;
} catch (Throwable t) {
DatabaseException dbe = new DatabaseException(t);
- if(procedure != null) procedure.exception(executeGraph, dbe);
+ if(procedure__ != null) procedure__.exception(executeGraph, dbe);
exception = dbe;
} finally {
if (entry != null) {
assert(entry.isReady());
// This does not throw
- entry.performFromCache(executeGraph, procedure_);
+ entry.performFromCache(executeGraph, procedure);
}
executeGraph.asyncBarrier.dec();
if(needsToBlock)
- executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
+ executeGraph.asyncBarrier.waitBarrier(procedure__, executeGraph);
}
if (BarrierTracing.BOOKKEEPING) {