Dynamic b-threads
Symbolic and dynamic b-threads
A. Symbolic b-threads
It is sometimes useful to have multiple b-threads as instances of the same class, differing from each other only by their parameters. For example, in one implementation of the game of Tic-Tac-Toe, the class AddThirdO has 48 instances. Each b-thread in the class is assigned a pair of O move events in a given line, it waits for the two to occur, and then requests the third O move event for the same line. The 48 instances cover the 6 lines (3 rows, 3 columns, and 2 diagonals) and all 6 permutations of the three events in that line.
To activate such symbolic b-thread the programmer should provide a constructor for the b-thread class which inherits from BThread, call the constructor with different parameters, and add and start all the returned instances. This approach was applied systematically to multiple classes in the Tic-Tac-Toe example as follows
package tictactoe.bThreads.tactics; import static bp.BProgram.bp; import static bp.BProgram.labelNextVerificationState; import static bp.eventSets.EventSetConstants.none; import java.util.HashSet; import java.util.Set; import tictactoe.events.O; import bp.BThread; import bp.exceptions.BPJException; /** * A scenario that tries to complete a row/column/diagonal of Os */ @SuppressWarnings("serial") public class AddThirdO extends BThread { private O firstSquare; private O secondSquare; private O triggeredEvent; @Override public void runBThread() throws BPJException { // interruptingEvents = new EventSet(gameOver); labelNextVerificationState("0"); // Wait for the first O bp.bSync(none, firstSquare, none); labelNextVerificationState("1"); // Wait for the second O bp.bSync(none, secondSquare, none); labelNextVerificationState("2"); // Request the third O bp.bSync(triggeredEvent, none, none); labelNextVerificationState("3"); bp.bSync(none, none, none); } /** * @param firstSquare * @param seconfSquare * @param triggeredEvent */ public AddThirdO(O firstSquare, O secondSquare, O triggeredEvent) { super(); this.firstSquare = firstSquare; this.secondSquare = secondSquare; this.triggeredEvent = triggeredEvent; this.setName("AddThirdO(" + firstSquare + "," + secondSquare + "," + triggeredEvent + ")"); } /** * Construct all instances */ static public Set<BThread> constructInstances() { Set<BThread> set = new HashSet<BThread>(); // All 6 permutations of three elements int[][] permutations = new int[][] { new int[] { 0, 1, 2 }, new int[] { 0, 2, 1 }, new int[] { 1, 0, 2 }, new int[] { 1, 2, 0 }, new int[] { 2, 0, 1 }, new int[] { 2, 1, 0 } }; for (int[] p : permutations) { // Run copies for each row for (int row = 0; row < 3; row++) { set.add(new AddThirdO(new O(row, p[0]), new O(row, p[1]), new O(row, p[2]))); } // Run copies for each column for (int col = 0; col < 3; col++) { set.add(new AddThirdO(new O(p[0], col), new O(p[1], col), new O(p[2], col))); } // Run copies for the main diagonal set.add(new AddThirdO(new O(p[0], p[0]), new O(p[1], p[1]), new O(p[2], p[2]))); // Run copies for the inverse diagonal set.add(new AddThirdO(new O(p[0], 2 - p[0]), new O( p[1], 2 - p[1]), new O(p[2], 2 - p[2]))); } return set; }
}
B. Dynamic b-threads
- B-threads are normally instantiated and added to the b-program in the runBApplication method.
- However, b-threads can also be created dynamically in two ways:
- Any thread or b-thread can create a new instance of the desired b-thread class, and call the bp.add method to add the b-thread to the b-program, and call the bthread.start method to start the b-thread. The b-thread will join the running b-threads in the next synchronization point.
- A running Java thread which is not a b-thread, may register itself as a b-thread and subsequently deregister, using the method calls XXXXXX and YYYYYY.
- Examples: