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