add notion of "torpedoability" to LoopFactory
[fleet.git] / src / edu / berkeley / fleet / loops / LoopFactory.java
index 7d5649c..0fed714 100644 (file)
@@ -8,8 +8,6 @@ import edu.berkeley.fleet.api.Instruction.Set;
 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.
@@ -42,9 +40,9 @@ public class LoopFactory {
     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>();
 
@@ -56,15 +54,24 @@ public class LoopFactory {
      *   @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)
@@ -76,9 +83,10 @@ public class LoopFactory {
     }
 
     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) {
@@ -89,6 +97,7 @@ public class LoopFactory {
 
     // Building Loops //////////////////////////////////////////////////////////////////////////////
 
+    Predicate   predicate = Predicate.Default;
     boolean     pending_interruptible = false;
     boolean     pending_recvToken = false;
     boolean     pending_recvOrCollect = false;
@@ -153,7 +162,8 @@ public class LoopFactory {
     /** 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;
     }
 
@@ -334,6 +344,11 @@ public class LoopFactory {
             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 &&