]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / BlockingAsyncProcedure.java
1 /*******************************************************************************
2  * Copyright (c) 2018 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.impl;
13
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;
21 import org.simantics.db.request.AsyncRead;
22
23 public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result>, Runnable {
24
25     private static final Object NO_RESULT = new Object();
26
27     private final Object key;
28     private final ReadGraphImpl queryGraph;
29     private final ReadGraphImpl callerGraph;
30     private final AsyncReadEntry<Result> entry;
31     private final AsyncProcedure<Result> procedure;
32     private PendingTaskSupport pendingTaskSupport;
33     private final boolean needsToBlock;
34     private Object result = NO_RESULT;
35     private Throwable exception = null;
36     
37     public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure, Object key, boolean needsToBlock) {
38         
39         // A new graph for evaluating the query with correct parent and asyncBarrier
40         queryGraph = callerGraph.withParent(entry, this, needsToBlock);
41         queryGraph.asyncBarrier.inc();
42         
43         // This makes sure that caller does not quit before dispatch
44         callerGraph.asyncBarrier.inc();
45
46         this.entry = entry;
47         this.procedure = procedure;
48         this.key = key;
49         this.queryGraph.asyncBarrier.inc();
50         this.callerGraph = callerGraph;
51         this.needsToBlock = needsToBlock;
52         if (BarrierTracing.BOOKKEEPING) {
53             BarrierTracing.registerBAP(this);
54         }
55     }
56
57     @Override
58     public void execute(AsyncReadGraph graph_, Result result) {
59         
60         this.result = result;
61         queryGraph.asyncBarrier.dec();
62         
63     }
64
65     @Override
66     public void exception(AsyncReadGraph graph_, Throwable t) {
67
68         this.exception = t;
69         queryGraph.asyncBarrier.dec();
70         
71     }
72     
73     public void waitBarrier() {
74         queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
75     }
76     
77     public void dec() {
78
79         queryGraph.asyncBarrier.dec();
80         
81     }
82
83     @SuppressWarnings("unchecked")
84     public Result get() throws DatabaseException {
85
86         if(needsToBlock)
87             queryGraph.asyncBarrier.waitBarrier(key, queryGraph);
88
89         if(exception != null) {
90             if(exception instanceof DatabaseException) throw (DatabaseException)exception;
91             throw new DatabaseException(exception);
92         } else {
93             return (Result)result;
94         }
95
96     }
97
98     @SuppressWarnings("unchecked")
99     public Result getResult() {
100         return (Result)result;
101     }
102
103     public Throwable getException() {
104         return exception;
105     }
106
107     @Override
108     public String toString() {
109         return "." + procedure; 
110     }
111     
112     @Override
113     public void run() {
114         
115         AsyncProcedure<Result> procedure__ = entry != null ? entry : procedure;
116
117         ReadGraphImpl executeGraph = callerGraph.withParent(callerGraph.parent, null, needsToBlock);
118         executeGraph.asyncBarrier.inc();
119         
120         // This counters the inc in the constructor 
121         callerGraph.asyncBarrier.dec();
122         
123         try {
124             if(procedure__ != null) {
125                 procedure__.execute(executeGraph, get());
126             }
127         } catch (DatabaseException e) {
128             if(procedure__ != null) procedure__.exception(executeGraph, e);
129             exception = e;
130         } catch (Throwable t) {
131             DatabaseException dbe = new DatabaseException(t);
132             if(procedure__ != null) procedure__.exception(executeGraph, dbe);
133             exception = dbe;
134         } finally {
135
136             if (entry != null) {
137                 assert(entry.isReady());
138                 // This does not throw
139                 entry.performFromCache(executeGraph, procedure);
140             }
141
142             executeGraph.asyncBarrier.dec();
143             if(needsToBlock)
144                 executeGraph.asyncBarrier.waitBarrier(procedure__, executeGraph);
145         }
146
147         if (BarrierTracing.BOOKKEEPING) {
148             BarrierTracing.unregisterBAP(this);
149         }
150
151     }
152     
153     public void print() {
154         System.err.println("BlockingAsyncProcedure");
155         System.err.println("-key: " + key);
156         System.err.println("-queryGraph: " + queryGraph);
157         System.err.println("-callerGraph: " + callerGraph);
158         System.err.println("-procedure: " + procedure);
159         System.err.println("-pendingTaskSupport: " + pendingTaskSupport);
160         System.err.println("-result: " + result);
161         System.err.println("-exception: " + exception);
162     }
163     
164     public Result performSync(AsyncRead<Result> request) throws DatabaseException {
165         try {
166             request.perform(queryGraph, this);
167         } finally {
168             dec();
169         }
170         return get();
171     }
172
173     public void performAsync(AsyncRead<Result> request) throws DatabaseException {
174         try {
175             request.perform(queryGraph, this);
176         } finally {
177             dec();
178         }
179     }
180
181 }