1 /**
2 * .
3 * Copyright � 1999 Erich P G.
4 *
5 */
6
7 package autohit.vm;
8
9 import autohit.utils.LockedQueue;
10
11 /**
12 * A VM automat. This is a different kind of VM context. Basically, it accepts a
13 * queue through which it can be controlled. Send it a Sim to run or an Integer(VM.STATE_*) to
14 * effect the state. NOTE that these are "requests." There is no guarentee that the order will
15 * be followed.
16 * <p>
17 * Here is a state diagram which shows some off the effects of control "requests." kill() is
18 * a special case, where another thread calls the Automat's kill() method.
19 * <p>
20 * <pre>
21 * | RUNNING | PAUSED | NO_VM
22 * A VM | ignored | ignored | vm is run
23 * STATE_NEW | ignored | ignored | ignored
24 * STATE_RUNNING | ignored | vm paused | ignored
25 * STATE_PAUSED | vm resumed | ignored | ignored
26 * STATE_DONE | vm discarded | vm discarded | ignored
27 * STATE_NO_VM | ignored | ignored | ignored
28 * die() | <--- VM Killed and Automat dies ------>
29 * </pre>
30 *
31 * <p>
32 * @author Erich P. Gatejen
33 * @version 1.0
34 * <i>Version History</i>
35 * <code>EPG - Initial - 12Feb99</code>
36 *
37 */
38 public class VMAutomat extends Thread {
39
40 // --- FINAL FIELDS ------------------------------------------------------
41
42 // --- FIELDS ------------------------------------------------------------
43
44 /**
45 * A runnable VM. This will be a fully implemented derived-class
46 * of VM.
47 */
48 private VM rVM;
49
50
51 /**
52 * The control queue. This thread will watch the queue for things to do.
53 */
54 private LockedQueue cQ;
55
56
57 /**
58 * Flags a kill order.
59 */
60 private boolean killed;
61
62
63 // --- PUBLIC METHODS ----------------------------------------------------
64
65 /**
66 * Constructor.
67 */
68 public VMAutomat(LockedQueue controlQueue) {
69
70 // Make this when we run. otherwise, we wont own it,
71 cQ = controlQueue;
72 rVM = null;
73 killed = false;
74
75 this.setDaemon(true);
76 }
77
78
79 /**
80 * Return the last known stable status. This is not 100% accurate, as the
81 * automate MAY be in the process of shifting status while this is being queried.
82 * It should be close enough for most purposes; the window of possible inaccuracy is
83 * perdy small...
84 *
85 * This method can be called by any thread.
86 *
87 * @return a VM.STATUS_* int value.
88 *
89 * @see autohit.vm.VM
90 */
91 public synchronized int getLastKnownStatus() {
92
93 if (rVM == null) return VM.STATE_NO_VM;
94 else return rVM.getState();
95 }
96
97
98 /**
99 * Kills the Automat as soon as possible.
100 */
101 public synchronized void kill(LockedQueue controlQueue) {
102
103 // Make this when we run. otherwise, we wont own it,
104 cQ = controlQueue;
105 rVM = null;
106
107 this.setDaemon(true);
108 }
109
110 /**
111 * Run the automat
112 */
113 public void run() {
114
115 Object dqo; // temporary dequeued object reference.
116 Integer tio; // temporary integer object
117
118 // Enter a loop until some other thread Kill()s me....
119 while (killed == false) {
120
121 // Nothing is running. Wait on the queue for a VM
122 if (!cQ.hasObject()) cQ.block(true);
123 dqo = cQ.get();
124
125 // Only interested in VMs
126 if (!(dqo instanceof VM)) continue;
127
128 // Any VM exception will make the context
129 // dump the VM. This will also catch the NullPointerException
130 // that would be caused by a spurious context thread unblock when
131 // a VM has not be set for execution.
132 try {
133
134 // Start the VM
135 rVM = (VM)dqo;
136 rVM.start();
137
138 // Specific VM loop
139 do {
140
141 // Check the queue for control objects... Control objects take precedence
142 // over instruciton execution.
143 if (cQ.hasObject()) {
144
145 dqo = cQ.get();
146
147 // Only care about Integers
148 if (dqo instanceof Integer) {
149
150 tio = (Integer)dqo;
151 switch(tio.intValue()) {
152
153 case VM.STATE_RUNNING:
154
155 // No need to check state.
156 rVM.resume();
157 break;
158
159 case VM.STATE_PAUSED:
160
161 // No need to check state.
162 // Since we have paused, this thread doesnt need
163 // to do anything until another control arrives.
164 // Go ahead and block on the queue.
165 rVM.pause();
166 cQ.block(true);
167 break;
168
169 case VM.STATE_DONE:
170
171 // DONE with this VM. Kill the reference.
172 rVM = null;
173
174 default:
175 // ignore all others
176 break;
177
178 } // end switch
179
180 } // end if Integer
181
182 } else {
183
184 // Go ahead and execute an instruction
185 rVM.execute();
186 }
187
188 } while (rVM != null);
189
190 } catch (Exception e) {
191 // Don't actuall have to do anything...
192 }
193
194 // The VM will die now... just in case.
195 rVM = null;
196
197 }
198
199 // Last out the door turn off the lights...
200 // DO NOT put ANY other code beyond the following statements
201 // or you are liable to deadlock other Threads.
202 yield();
203 }
204
205 // --- PRIVATE METHODS ---------------------------------------------------
206
207 }
|