import edu.berkeley.fleet.api.Instruction.Set.*;
import static edu.berkeley.fleet.util.BitManipulations.*;
-// FIXME: is it legitimate to send a torpedo to a count==1 loop?
-// FIXME: is it legitimate to send a torpedo to a count>1 loop?
/**
*
* A helper class for building loops of instructions.
public final Dock dock;
public final String friendlyName;
public final int count;
+ public final boolean torpedoable;
private final Context ctx;
- private Predicate predicate = Predicate.Default;
private LoopFactory next = null;
private ArrayList<Instruction> instructions = new ArrayList<Instruction>();
* @arg count the number of times to execute this loop; <tt>0</tt> means continue until torpedoed
*/
public LoopFactory(Context ctx, Dock dock, int count) {
- this(ctx, dock, count, dock.toString(), null);
+ this(ctx, dock, count, count==0, dock.toString(), null);
+ }
+ public LoopFactory(Context ctx, Dock dock, int count, boolean torpedoable) {
+ this(ctx, dock, count, torpedoable, dock.toString(), null);
}
public LoopFactory(Context ctx, Dock dock, int count, String friendlyName) {
- this(ctx, dock, count, friendlyName, null);
+ this(ctx, dock, count, count==0, friendlyName);
+ }
+ public LoopFactory(Context ctx, Dock dock, int count, boolean torpedoable, String friendlyName) {
+ this(ctx, dock, count, torpedoable, friendlyName, null);
}
- private LoopFactory(Context ctx, Dock dock, int count, String friendlyName, LoopFactory prev) {
+ private LoopFactory(Context ctx, Dock dock, int count, boolean torpedoable, String friendlyName, LoopFactory prev) {
this.ctx = ctx;
this.dock = dock;
this.count = count;
+ if (count==0 && !torpedoable)
+ throw new RuntimeException("count==0 loops must be torpedoable");
+ this.torpedoable = torpedoable;
this.friendlyName = friendlyName;
ctx.loopFactories.add(this);
if (ctx.startupLoopFactories.get(dock) == null)
}
public LoopFactory makeNext(int new_count) { return makeNext(new_count, null); }
- public LoopFactory makeNext(int new_count, String newFriendlyName) {
+ public LoopFactory makeNext(int new_count, String newFriendlyName) { return makeNext(new_count, new_count==0, newFriendlyName); }
+ public LoopFactory makeNext(int new_count, boolean newTorpedoable, String newFriendlyName) {
if (next != null) throw new RuntimeException("loop already has a successor");
- return new LoopFactory(ctx, dock, new_count, newFriendlyName, this);
+ return new LoopFactory(ctx, dock, new_count, newTorpedoable, newFriendlyName, this);
}
public LoopFactory getNext() { return next; }
private void setNext(LoopFactory next) {
// Building Loops //////////////////////////////////////////////////////////////////////////////
+ Predicate predicate = Predicate.Default;
boolean pending_interruptible = false;
boolean pending_recvToken = false;
boolean pending_recvOrCollect = false;
/** must be followed immediately by a move-based instruction */
public void abortLoopIfTorpedoPresent() {
flush_pending();
- //if (count!=0) throw new RuntimeException("currently, only forever-loops may be sensitive to torpedoes");
+ if (!torpedoable)
+ throw new RuntimeException("invocation of abortLoopIfTorpedoPresent() in a non-torpedoable LoopFactory");
pending_interruptible = true;
}
if (dock.isInputDock())
ic.add(new Instruction.Flush(dock, true, Predicate.FlagD));
}
+
+ // FIXME: need to somehow deal with count!=0 loops that are
+ // torpedoable; they need to wait for a torpedo to arrive
+ // after exhausting their count.
+
if (count!=1) {
ic.add(new Instruction.Tail(dock));
if (!instructionFifoSizeCheckDisabled &&