1 /*******************************************************************************
2 * Copyright (c) 2018 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Semantum Oy - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.impl;
14 import org.simantics.db.AsyncReadGraph;
15 import org.simantics.db.exception.DatabaseException;
16 import org.simantics.db.impl.graph.BarrierTracing;
17 import org.simantics.db.impl.graph.ReadGraphImpl;
18 import org.simantics.db.impl.query.AsyncReadEntry;
19 import org.simantics.db.impl.query.PendingTaskSupport;
20 import org.simantics.db.procedure.AsyncProcedure;
22 public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
24 private static final Object NO_RESULT = new Object();
26 public final Object key;
27 public final ReadGraphImpl queryGraph;
28 public final ReadGraphImpl callerGraph;
29 public final AsyncProcedure<Result> procedure;
30 public PendingTaskSupport pendingTaskSupport;
31 public Object result = NO_RESULT;
32 public Throwable exception = null;
34 private ReadGraphImpl queryGraph() {
38 public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure, Object key, boolean needsToBlock) {
40 // A new graph for evaluating the query with correct parent and asyncBarrier
41 queryGraph = callerGraph.withParent(entry, () -> {
43 dispatchProcedure(queryGraph(), callerGraph, entry, procedure, needsToBlock);
47 queryGraph.asyncBarrier.inc();
49 this.procedure = procedure;
51 this.queryGraph.asyncBarrier.inc();
52 this.callerGraph = callerGraph;
53 if (BarrierTracing.BOOKKEEPING) {
54 BarrierTracing.registerBAP(this);
59 public void execute(AsyncReadGraph graph_, Result result) {
62 queryGraph.asyncBarrier.dec();
67 public void exception(AsyncReadGraph graph_, Throwable t) {
70 queryGraph.asyncBarrier.dec();
74 public void waitBarrier() {
75 queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
80 queryGraph.asyncBarrier.dec();
84 @SuppressWarnings("unchecked")
85 public Result get() throws DatabaseException {
87 queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
89 if(exception != null) {
90 if(exception instanceof DatabaseException) throw (DatabaseException)exception;
91 throw new DatabaseException(exception);
93 return (Result)result;
98 @SuppressWarnings("unchecked")
99 public Result getResult() {
100 return (Result)result;
103 public Throwable getException() {
108 public String toString() {
109 return "." + procedure;
112 private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure_, boolean needsToBlock) {
114 AsyncProcedure<Result> procedure = entry != null ? entry : procedure_;
116 ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent);
117 executeGraph.asyncBarrier.inc();
119 if(procedure != null) {
120 procedure.execute(executeGraph, get());
122 } catch (DatabaseException e) {
123 if(procedure != null) procedure.exception(executeGraph, e);
125 } catch (Throwable t) {
126 DatabaseException dbe = new DatabaseException(t);
127 if(procedure != null) procedure.exception(executeGraph, dbe);
132 assert(entry.isReady());
133 // This does not throw
134 entry.performFromCache(executeGraph, procedure_);
137 executeGraph.asyncBarrier.dec();
139 executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
142 if (BarrierTracing.BOOKKEEPING) {
143 BarrierTracing.unregisterBAP(this);