8b74ac1a7db99f51c7fe8dcf68cc06fce8bb2d2f
[fleet.git] / src / edu / berkeley / fleet / interpreter / InstructionBenkoBox.java
1 package edu.berkeley.fleet.interpreter;
2 import edu.berkeley.sbp.util.ANSI;
3 import edu.berkeley.fleet.api.*;
4 import edu.berkeley.fleet.api.Instruction;
5
6 import java.util.*;
7
8 /** anything that has a source (instruction horn) address on the switch fabric */
9 abstract class InstructionBenkoBox extends InterpreterBenkoBox {
10
11     /** the currently executing instruction */
12     private Instruction.Executable executing = null;
13
14     /** all instructions waiting to be executed (excludes executing) */
15     private Queue<Instruction.Executable> instructions = new LinkedList<Instruction.Executable>();
16
17     /** count of how many "standing instruction only" kills remain to be executed */
18     private int killNextStandingInstruction = 0;
19
20     InstructionBenkoBox(InterpreterShip ship, String name, String[] ports) {
21         super(ship, name, ports);
22     }
23
24     public void kill(int count, boolean killOnlyStandingInstructions) {
25         if (count==0) return;
26         if (!killOnlyStandingInstructions) {
27             if (executing != null) { executing = null; count--; }
28             for(;count > 0;count--) {
29                 if (instructions.size()==0)
30                     throw new RuntimeException("deadlocked " + this + " by killing too many instructions");
31                 instructions.remove();
32             }
33         } else {
34             if (count != 1) throw new RuntimeException("this should never happen");
35             this.killNextStandingInstruction++;
36         }
37     }
38
39     /** an instruction arrives from the instruction horn */
40     void addInstruction(Instruction.Executable instr) {
41         if (killNextStandingInstruction > 0) { /* FIXME technically we should refuse to take the next instruction here */ }
42         instructions.add(instr);
43     }
44
45     protected void shutdown(boolean leaveAsInbox) {
46         if (!(executing != null || instructions.size() > 0)) return;
47         Log.println(ANSI.red(" WARNING: you left instructions on the instruction queue of port " +
48                              this + "; they are:"));
49         if (executing != null)
50             Log.println("   " + executing);
51         for(Instruction.Executable i : instructions)
52             Log.println("   " + i);
53     }
54
55     // interface to subclass ///////////////////////////////////////////////////////////////////////
56
57     /** this will be invoked periodically; should return true to "consume" an instruction, false to leave it executing */
58     protected abstract boolean service(Instruction.Executable instr);
59
60     protected final void service() {
61         if (executing == null)
62             if (instructions.size() > 0)
63                 executing = instructions.remove();
64             else
65                 return;
66
67         if (executing != null && killNextStandingInstruction>0 && executing.isStanding()) {
68             executing = null;
69             killNextStandingInstruction--;
70             return;
71         }
72
73         boolean ret = service(executing);
74         if (!ret) return;
75         if (executing.requeue) {
76             executing = executing.decrementCount();
77             if (executing != null)
78                 addInstruction(executing);
79             executing = null;
80
81         } else {
82             if (executing != null && !executing.isStanding())
83                 executing = executing.decrementCount();
84         }
85     }
86
87
88 }