]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/SCLRealm.java
Merge commit 'bf75fd9'
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / SCLRealm.java
1 package org.simantics.modeling.scl;\r
2 \r
3 import java.io.IOException;\r
4 import java.util.Map;\r
5 import java.util.concurrent.ExecutorService;\r
6 import java.util.concurrent.LinkedBlockingQueue;\r
7 import java.util.concurrent.Semaphore;\r
8 import java.util.concurrent.ThreadFactory;\r
9 import java.util.concurrent.ThreadPoolExecutor;\r
10 import java.util.concurrent.TimeUnit;\r
11 \r
12 import org.simantics.databoard.Bindings;\r
13 import org.simantics.databoard.binding.Binding;\r
14 import org.simantics.databoard.binding.mutable.Variant;\r
15 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;\r
16 import org.simantics.modeling.SCLTypeUtils;\r
17 import org.simantics.scl.compiler.commands.CommandSession;\r
18 import org.simantics.scl.compiler.types.Type;\r
19 import org.simantics.scl.runtime.SCLContext;\r
20 import org.simantics.scl.runtime.function.Function;\r
21 import org.simantics.scl.runtime.tuple.Tuple0;\r
22 import org.simantics.simulator.variable.NodeManager;\r
23 import org.simantics.simulator.variable.Realm;\r
24 import org.slf4j.Logger;\r
25 import org.slf4j.LoggerFactory;\r
26 \r
27 import gnu.trove.map.hash.THashMap;\r
28 \r
29 public class SCLRealm implements Realm {\r
30     private static final Logger LOGGER = LoggerFactory.getLogger(SCLRealm.class);\r
31 \r
32     public static final String SCL = "scl";\r
33     \r
34     THashMap<String,Type> contextTypes = new THashMap<String,Type>();\r
35     \r
36     CommandSession connection;\r
37     String id;\r
38     Thread executorThread;\r
39     ExecutorService executor = new ThreadPoolExecutor(0, 1, 60, TimeUnit.SECONDS,\r
40             new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {\r
41         @Override\r
42         public Thread newThread(Runnable r) {\r
43             executorThread = new Thread(r);\r
44             return executorThread;\r
45         }\r
46     });\r
47     \r
48     Semaphore beginSyncExec = new Semaphore(0);\r
49     Semaphore endSyncExec = new Semaphore(0);\r
50     \r
51     SCLNodeManager nodeManager;\r
52     \r
53     Runnable scheduleSyncExec = new Runnable() {\r
54         @Override\r
55         public void run() {\r
56             beginSyncExec.release();\r
57             try {\r
58                 endSyncExec.acquire();\r
59             } catch (InterruptedException e) {\r
60             }\r
61         }\r
62     };\r
63     \r
64     SCLRealm(CommandSession connection, String id) {\r
65         this.connection = connection;\r
66         this.id = id;\r
67         this.nodeManager = new SCLNodeManager(this);\r
68     }\r
69 \r
70     public String getId() {\r
71         return id;\r
72     }\r
73     \r
74     public CommandSession getConnection() {\r
75         return connection;\r
76     }\r
77     \r
78     public Thread getThread() {\r
79         return executorThread;\r
80     }\r
81     \r
82     @SuppressWarnings({ "rawtypes", "unchecked" })\r
83     public Object syncExec(Function fun) throws InterruptedException {\r
84         executor.execute(scheduleSyncExec);\r
85         \r
86         SCLContext context = SCLContext.getCurrent();\r
87         CommandSession oldConnection = (CommandSession)context.put(SCL, connection);\r
88         \r
89         try {\r
90             beginSyncExec.acquire();\r
91             Thread oldThread = executorThread;\r
92             executorThread = Thread.currentThread();\r
93             try {\r
94                 return fun.apply(Tuple0.INSTANCE);\r
95             } finally {\r
96                 executorThread = oldThread;\r
97                 endSyncExec.release();\r
98             }\r
99         } finally {\r
100             context.put(SCL, oldConnection);\r
101         }\r
102     }\r
103     \r
104     @SuppressWarnings("rawtypes")\r
105     public void asyncExec(final Function fun) {\r
106         executor.execute(new Runnable() {\r
107             @SuppressWarnings("unchecked")\r
108             @Override\r
109             public void run() {\r
110                 SCLContext context = SCLContext.getCurrent();\r
111                 context.put(SCL, connection);\r
112                 fun.apply(Tuple0.INSTANCE);\r
113             }\r
114         });\r
115     }\r
116 \r
117     @Override\r
118     public void syncExec(Runnable runnable) throws InterruptedException {\r
119         \r
120         if(executorThread == Thread.currentThread()) {\r
121             try {\r
122                 runnable.run();\r
123             } catch (Throwable t) {\r
124                 LOGGER.error("Runnable failed in syncExec.", t);\r
125             } finally {\r
126             }\r
127             return;\r
128         }\r
129 \r
130         executor.execute(scheduleSyncExec);\r
131         \r
132         beginSyncExec.acquire();\r
133         Thread oldThread = executorThread;\r
134         executorThread = Thread.currentThread();\r
135         try {\r
136             runnable.run();\r
137         } catch (Throwable t) {\r
138             LOGGER.error("Runnable failed in syncExec.", t);\r
139         } finally {\r
140             executorThread = oldThread;\r
141             endSyncExec.release();\r
142         }\r
143     }\r
144 \r
145     @Override\r
146     public void asyncExec(Runnable runnable) {\r
147 \r
148         if(executorThread == Thread.currentThread()) {\r
149             try {\r
150                 runnable.run();\r
151             } catch (Throwable t) {\r
152                 LOGGER.error("Runnable failed in asyncExec.", t);\r
153             } finally {\r
154             }\r
155             return;\r
156         }\r
157         \r
158         executor.execute(runnable);\r
159     }\r
160     \r
161     public void refreshVariables() {\r
162         nodeManager.refreshVariables();\r
163     }\r
164     \r
165     public void refreshVariablesSync() {\r
166         nodeManager.refreshVariablesSync();\r
167     }\r
168 \r
169     public void close() {\r
170         SCLSessionManager.CONNECTIONS.remove(id);\r
171         executor.shutdown();\r
172         try {\r
173             executor.awaitTermination(500L, TimeUnit.MILLISECONDS);\r
174         } catch (InterruptedException e) {\r
175         }\r
176         //connection.close();\r
177     }\r
178 \r
179     public NodeManager<String> getNodeManager() {\r
180         return nodeManager;\r
181     }\r
182     \r
183     private SCLState getState() {\r
184         SCLState state = new SCLState();\r
185         for(String key : connection.getVariables()) {\r
186                 Object value = connection.getVariableValue(key);\r
187                 try {\r
188                         Binding b = Bindings.getBinding(value.getClass());\r
189                         state.values.put(key, new Variant(b, value));\r
190                 } catch (Exception e) {\r
191                 }\r
192         }\r
193         return state;\r
194     }\r
195     \r
196     public void applyState(byte[] blob) {\r
197         try {\r
198                         SCLState state = (SCLState)SCLState.BINDING.serializer().deserialize(blob);\r
199                 for(Map.Entry<String,Variant> entry : state.values.entrySet()) {\r
200                         String key = entry.getKey();\r
201                         Variant value = entry.getValue();\r
202                         Type type = SCLTypeUtils.getType(value.type());\r
203                         if (type.getClassId() != Type.VAR_ID) {\r
204                             // do not add the property if type cannot be inferred\r
205                             connection.setVariable(key, type, value.getValue());\r
206                         }\r
207                 }\r
208                 } catch (RuntimeSerializerConstructionException e) {\r
209                 } catch (IOException e) {\r
210                 }\r
211     }\r
212     \r
213     public byte[] serialize() {\r
214         SCLState state = getState();\r
215         try {\r
216                         return SCLState.BINDING.serializer().serialize(state);\r
217                 } catch (RuntimeSerializerConstructionException e) {\r
218                         return null;\r
219                 } catch (IOException e) {\r
220                         return null;\r
221                 }\r
222     }\r
223     \r
224 }\r