package org.simantics.db.impl;
import org.simantics.db.AsyncReadGraph;
-import org.simantics.db.common.utils.Logger;
import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.impl.graph.BarrierTracing;
import org.simantics.db.impl.graph.ReadGraphImpl;
+import org.simantics.db.impl.query.AsyncReadEntry;
+import org.simantics.db.impl.query.PendingTaskSupport;
import org.simantics.db.procedure.AsyncProcedure;
public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
private static final Object NO_RESULT = new Object();
- private final Object key;
- private final ReadGraphImpl graph;
- private final AsyncProcedure<Result> procedure;
+ public final Object key;
+ public final ReadGraphImpl queryGraph;
+ public final ReadGraphImpl callerGraph;
+ public final AsyncProcedure<Result> procedure;
+ public PendingTaskSupport pendingTaskSupport;
+ public Object result = NO_RESULT;
+ public Throwable exception = null;
- 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);
+
+ });
+
+ queryGraph.asyncBarrier.inc();
- public BlockingAsyncProcedure(ReadGraphImpl graph, AsyncProcedure<Result> procedure, Object key) {
this.procedure = procedure;
this.key = key;
- this.graph = ReadGraphImpl.newAsync(graph);
- this.graph.asyncBarrier.inc();
+ this.queryGraph.asyncBarrier.inc();
+ this.callerGraph = callerGraph;
+ if (BarrierTracing.BOOKKEEPING) {
+ BarrierTracing.registerBAP(this);
+ }
}
@Override
- public void execute(AsyncReadGraph graph, Result result) {
+ public void execute(AsyncReadGraph graph_, Result result) {
+
this.result = result;
- this.graph.asyncBarrier.dec();
- try {
- if(procedure != null) procedure.execute(graph, result);
- } catch (Throwable throwable) {
- Logger.defaultLogError("AsyncProcedure.execute threw for " + procedure, throwable);
- }
+ queryGraph.asyncBarrier.dec();
+
}
@Override
- public void exception(AsyncReadGraph graph, Throwable t) {
+ public void exception(AsyncReadGraph graph_, Throwable t) {
+
this.exception = t;
- try {
- if(procedure != null) procedure.exception(graph, t);
- } catch (Throwable throwable) {
- Logger.defaultLogError("AsyncProcedure.exception threw for " + procedure, throwable);
- } finally {
- this.graph.asyncBarrier.dec();
- }
+ queryGraph.asyncBarrier.dec();
+
+ }
+
+ public void waitBarrier() {
+ queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
+ }
+
+ public void dec() {
+
+ queryGraph.asyncBarrier.dec();
+
}
@SuppressWarnings("unchecked")
public Result get() throws DatabaseException {
- graph.asyncBarrier.waitBarrier(key, graph);
+ queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
if(exception != null) {
if(exception instanceof DatabaseException) throw (DatabaseException)exception;
public String toString() {
return "." + procedure;
}
+
+ private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure_, boolean needsToBlock) {
+
+ AsyncProcedure<Result> procedure = entry != null ? entry : procedure_;
+
+ ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent);
+ executeGraph.asyncBarrier.inc();
+ try {
+ if(procedure != null) {
+ procedure.execute(executeGraph, get());
+ }
+ } catch (DatabaseException 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);
+ exception = dbe;
+ } finally {
+
+ if (entry != null) {
+ assert(entry.isReady());
+ // This does not throw
+ entry.performFromCache(executeGraph, procedure_);
+ }
+
+ executeGraph.asyncBarrier.dec();
+ if(needsToBlock)
+ executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
+ }
+
+ if (BarrierTracing.BOOKKEEPING) {
+ BarrierTracing.unregisterBAP(this);
+ }
+
+ }
}