1 package org.simantics.modeling.scl;
3 import java.io.IOException;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.LinkedBlockingQueue;
7 import java.util.concurrent.Semaphore;
8 import java.util.concurrent.ThreadFactory;
9 import java.util.concurrent.ThreadPoolExecutor;
10 import java.util.concurrent.TimeUnit;
12 import org.simantics.databoard.Bindings;
13 import org.simantics.databoard.binding.Binding;
14 import org.simantics.databoard.binding.mutable.Variant;
15 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
16 import org.simantics.modeling.SCLTypeUtils;
17 import org.simantics.scl.compiler.commands.CommandSession;
18 import org.simantics.scl.compiler.types.Type;
19 import org.simantics.scl.runtime.SCLContext;
20 import org.simantics.scl.runtime.function.Function;
21 import org.simantics.scl.runtime.tuple.Tuple0;
22 import org.simantics.simulator.variable.NodeManager;
23 import org.simantics.simulator.variable.Realm;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import gnu.trove.map.hash.THashMap;
29 public class SCLRealm implements Realm {
30 private static final Logger LOGGER = LoggerFactory.getLogger(SCLRealm.class);
32 public static final String SCL = "scl";
34 THashMap<String,Type> contextTypes = new THashMap<String,Type>();
36 CommandSession connection;
38 Thread executorThread;
39 ExecutorService executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,
40 new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
42 public Thread newThread(Runnable r) {
43 executorThread = new Thread(r);
44 return executorThread;
48 Semaphore beginSyncExec = new Semaphore(0);
49 Semaphore endSyncExec = new Semaphore(0);
51 SCLNodeManager nodeManager;
53 Runnable scheduleSyncExec = new Runnable() {
56 beginSyncExec.release();
58 endSyncExec.acquire();
59 } catch (InterruptedException e) {
64 SCLRealm(CommandSession connection, String id) {
65 this.connection = connection;
67 this.nodeManager = new SCLNodeManager(this);
70 public String getId() {
74 public CommandSession getConnection() {
78 public Thread getThread() {
79 return executorThread;
82 @SuppressWarnings({ "rawtypes", "unchecked" })
83 public Object syncExec(Function fun) throws InterruptedException {
84 executor.execute(scheduleSyncExec);
86 SCLContext context = SCLContext.getCurrent();
87 CommandSession oldConnection = (CommandSession)context.put(SCL, connection);
90 beginSyncExec.acquire();
91 Thread oldThread = executorThread;
92 executorThread = Thread.currentThread();
94 return fun.apply(Tuple0.INSTANCE);
96 executorThread = oldThread;
97 endSyncExec.release();
100 context.put(SCL, oldConnection);
104 @SuppressWarnings("rawtypes")
105 public void asyncExec(final Function fun) {
106 executor.execute(new Runnable() {
107 @SuppressWarnings("unchecked")
110 SCLContext context = SCLContext.getCurrent();
111 context.put(SCL, connection);
112 fun.apply(Tuple0.INSTANCE);
118 public void syncExec(Runnable runnable) throws InterruptedException {
120 if(executorThread == Thread.currentThread()) {
123 } catch (Throwable t) {
124 LOGGER.error("Runnable failed in syncExec.", t);
130 executor.execute(scheduleSyncExec);
132 beginSyncExec.acquire();
133 Thread oldThread = executorThread;
134 executorThread = Thread.currentThread();
137 } catch (Throwable t) {
138 LOGGER.error("Runnable failed in syncExec.", t);
140 executorThread = oldThread;
141 endSyncExec.release();
146 public void asyncExec(Runnable runnable) {
148 if(executorThread == Thread.currentThread()) {
151 } catch (Throwable t) {
152 LOGGER.error("Runnable failed in asyncExec.", t);
158 executor.execute(runnable);
161 public void refreshVariables() {
162 nodeManager.refreshVariables();
165 public void refreshVariablesSync() {
166 nodeManager.refreshVariablesSync();
169 public void close() {
170 SCLSessionManager.CONNECTIONS.remove(id);
173 executor.awaitTermination(500L, TimeUnit.MILLISECONDS);
174 } catch (InterruptedException e) {
176 //connection.close();
179 public NodeManager<String> getNodeManager() {
183 private SCLState getState() {
184 SCLState state = new SCLState();
185 for(String key : connection.getVariables()) {
186 Object value = connection.getVariableValue(key);
188 Binding b = Bindings.getBinding(value.getClass());
189 state.values.put(key, new Variant(b, value));
190 } catch (Exception e) {
196 public void applyState(byte[] blob) {
198 SCLState state = (SCLState)SCLState.BINDING.serializer().deserialize(blob);
199 for(Map.Entry<String,Variant> entry : state.values.entrySet()) {
200 String key = entry.getKey();
201 Variant value = entry.getValue();
202 Type type = SCLTypeUtils.getType(value.type());
203 if (type.getClassId() != Type.VAR_ID) {
204 // do not add the property if type cannot be inferred
205 connection.setVariable(key, type, value.getValue());
208 } catch (RuntimeSerializerConstructionException e) {
209 } catch (IOException e) {
213 public byte[] serialize() {
214 SCLState state = getState();
216 return SCLState.BINDING.serializer().serialize(state);
217 } catch (RuntimeSerializerConstructionException e) {
219 } catch (IOException e) {