b22d9c5c1b4b3fc6c2cf7341ecaf5693799a0b7b
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / launch / MachineProcess.java
1 package net.mograsim.plugin.launch;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import org.eclipse.core.runtime.IStatus;
7 import org.eclipse.core.runtime.PlatformObject;
8 import org.eclipse.core.runtime.Status;
9 import org.eclipse.debug.core.DebugEvent;
10 import org.eclipse.debug.core.DebugException;
11 import org.eclipse.debug.core.DebugPlugin;
12 import org.eclipse.debug.core.ILaunch;
13 import org.eclipse.debug.core.ILaunchConfiguration;
14 import org.eclipse.debug.core.model.IDebugTarget;
15 import org.eclipse.debug.core.model.IProcess;
16 import org.eclipse.debug.core.model.IStreamsProxy;
17 import org.eclipse.debug.core.model.ISuspendResume;
18
19 import net.mograsim.logic.model.LogicExecuter;
20 import net.mograsim.machine.Machine;
21 import net.mograsim.machine.MachineDefinition;
22 import net.mograsim.plugin.MograsimActivator;
23
24 public class MachineProcess extends PlatformObject implements IProcess, ISuspendResume
25 {
26         private final ILaunch launch;
27         private final Machine machine;
28         private final LogicExecuter exec;
29
30         private boolean running;
31
32         public MachineProcess(ILaunch launch, MachineDefinition machineDefinition)
33         {
34                 this.launch = launch;
35                 this.machine = machineDefinition.createNew();
36                 this.exec = new LogicExecuter(machine.getTimeline());
37
38                 exec.startLiveExecution();
39                 running = true;
40
41                 launch.addProcess(this);
42                 fireCreationEvent();
43         }
44
45         public Machine getMachine()
46         {
47                 return machine;
48         }
49
50         @Override
51         public ILaunch getLaunch()
52         {
53                 return launch;
54         }
55
56         public String getName()
57         {
58                 return "Mograsim machine \"" + machine.getDefinition().getId() + '"';
59         }
60
61         @Override
62         public String getLabel()
63         {
64                 return getName() + " (" + getStatusString() + ')';
65         }
66
67         public String getStatusString()
68         {
69                 return isTerminated() ? "terminated" : isSuspended() ? "paused" : "running";
70         }
71
72         public void setExecutionSpeed(double speed)
73         {
74                 exec.setSpeedFactor(speed);
75         }
76
77         @Override
78         public boolean isSuspended()
79         {
80                 return exec.isPaused();
81         }
82
83         @Override
84         public boolean canSuspend()
85         {
86                 return !isTerminated() && !isSuspended();
87         }
88
89         @Override
90         public void suspend() throws DebugException
91         {
92                 if (isTerminated())
93                         throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED,
94                                         "Can't suspend a terminated MachineProcess", null));
95                 if (isSuspended())
96                         throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED,
97                                         "Can't suspend a suspended MachineProcess", null));
98
99                 exec.pauseLiveExecution();
100                 fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
101         }
102
103         @Override
104         public boolean canResume()
105         {
106                 return !isTerminated() && isSuspended();
107         }
108
109         @Override
110         public void resume() throws DebugException
111         {
112                 if (isTerminated())
113                         throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED,
114                                         "Can't resume a terminated MachineProcess", null));
115                 if (!isSuspended())
116                         throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED,
117                                         "Can't resume a non-suspended MachineProcess", null));
118
119                 exec.unpauseLiveExecution();
120                 fireResumeEvent(DebugEvent.CLIENT_REQUEST);
121         }
122
123         @Override
124         public boolean isTerminated()
125         {
126                 return !running;
127         }
128
129         @Override
130         public boolean canTerminate()
131         {
132                 return !isTerminated();
133         }
134
135         @Override
136         public void terminate() throws DebugException
137         {
138                 if (isTerminated())
139                         return;
140
141                 exec.stopLiveExecution();
142                 running = false;
143                 fireTerminateEvent();
144         }
145
146         @Override
147         public int getExitValue() throws DebugException
148         {
149                 if (!isTerminated())
150                         throw new DebugException(new Status(IStatus.ERROR, MograsimActivator.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED,
151                                         "Can't get the exit value of a running process", null));
152
153                 return 0;
154         }
155
156         @Override
157         public IStreamsProxy getStreamsProxy()
158         {
159                 return null;
160         }
161
162         private Map<String, String> attributes;
163
164         @Override
165         public void setAttribute(String key, String value)
166         {
167                 if (attributes == null)
168                         attributes = new HashMap<>(5);
169                 Object origVal = attributes.get(key);
170                 if (origVal != null && origVal.equals(value))
171                         return;
172                 attributes.put(key, value);
173                 fireChangeEvent();
174         }
175
176         @Override
177         public String getAttribute(String key)
178         {
179                 if (attributes == null)
180                         return null;
181                 return attributes.get(key);
182         }
183
184         @SuppressWarnings("unchecked")
185         @Override
186         public <T> T getAdapter(Class<T> adapter)
187         {
188                 if (adapter.equals(IProcess.class))
189                         return (T) this;
190
191                 if (adapter.equals(IDebugTarget.class))
192                 {
193                         ILaunch launch = getLaunch();
194                         IDebugTarget[] targets = launch.getDebugTargets();
195                         for (int i = 0; i < targets.length; i++)
196                                 if (this.equals(targets[i].getProcess()))
197                                         return (T) targets[i];
198                         return null;
199                 }
200
201                 if (adapter.equals(ILaunch.class))
202                         return (T) getLaunch();
203
204                 if (adapter.equals(ILaunchConfiguration.class))
205                         return (T) getLaunch().getLaunchConfiguration();
206
207                 return super.getAdapter(adapter);
208         }
209
210         /**
211          * Fires a creation event.
212          */
213         private void fireCreationEvent()
214         {
215                 fireEvent(new DebugEvent(this, DebugEvent.CREATE));
216         }
217
218         /**
219          * Fires a change event.
220          */
221         private void fireChangeEvent()
222         {
223                 fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
224         }
225
226         /**
227          * Fires a resume for this debug element with the specified detail code.
228          *
229          * @param detail detail code for the resume event, such as <code>DebugEvent.STEP_OVER</code>
230          */
231         private void fireResumeEvent(int detail)
232         {
233                 fireEvent(new DebugEvent(this, DebugEvent.RESUME, detail));
234         }
235
236         /**
237          * Fires a suspend event for this debug element with the specified detail code.
238          *
239          * @param detail detail code for the suspend event, such as <code>DebugEvent.BREAKPOINT</code>
240          */
241         private void fireSuspendEvent(int detail)
242         {
243                 fireEvent(new DebugEvent(this, DebugEvent.SUSPEND, detail));
244         }
245
246         /**
247          * Fires a terminate event.
248          */
249         private void fireTerminateEvent()
250         {
251                 fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
252         }
253
254         /**
255          * Fires the given debug event.
256          *
257          * @param event debug event to fire
258          */
259         private static void fireEvent(DebugEvent event)
260         {
261                 DebugPlugin manager = DebugPlugin.getDefault();
262                 if (manager != null)
263                         manager.fireDebugEventSet(new DebugEvent[] { event });
264         }
265 }