package simple; import java.util.ArrayList; import java.util.List; import jvstm.CommitException; import jvstm.ParallelTask; import jvstm.Transaction; import jvstm.VBox; /** * Test the following scenario * A writes x=1 * A spawns B * B spawns C e D * C writes x=2 * C reads y=0 * D writes y=1 * D commits * C aborts * at this point, another top level transaction Z tries to write to x and acquires ownership of the VBox * when in fact the ownership belonged to A * * * @author nmld * */ public class AbortedParallelTxTest { protected static final VBox<Integer> x = new VBox<Integer>(0); protected static final VBox<Integer> y = new VBox<Integer>(0); public static class TopLevelA extends Thread { public void run() { Transaction.begin(false); try { int valX = x.get(); x.put(valX + 1); List<ParallelTask<Void>> tasks = new ArrayList<ParallelTask<Void>>(); tasks.add(new NestedB()); Transaction.current().manageNestedParallelTxs(tasks); Transaction.commit(); throw new AssertionError("TopLevelA should not commit because of Z"); } catch (CommitException ce) { Transaction.abort(); } } } public static class NestedB extends ParallelTask<Void> { @Override public Void execute() throws Throwable { List<ParallelTask<Void>> tasks = new ArrayList<ParallelTask<Void>>(); tasks.add(new NestedC()); tasks.add(new NestedD()); Transaction.current().manageNestedParallelTxs(tasks); return null; } } public static class NestedC extends ParallelTask<Void> { private boolean isRepeating = false; @Override public Void execute() throws Throwable { if (isRepeating) { Thread.sleep(3000); } int valX = x.get(); x.put(valX + 1); int valY = y.get(); if (valX != 1) { throw new AssertionError("NestedC read valX != 1: " + valX); } if (!isRepeating && valY != 0) { throw new AssertionError("NestedC was not yet aborted, yet it read valY != 0: " + valY); } if (isRepeating && valY != 1) { throw new AssertionError("NestedC was already aborted, yet it read valY != 1: " + valY); } isRepeating = true; Thread.sleep(750); return null; } } public static class NestedD extends ParallelTask<Void> { @Override public Void execute() throws Throwable { Thread.sleep(500); int valY = y.get(); y.put(valY + 1); if (valY != 0) { throw new AssertionError("NestedD read valY != 0: " + valY); } return null; } } public static class TopLevelZ extends Thread { public void run() { try { Transaction.begin(false); Thread.sleep(2000); int valX = x.get(); x.put(valX + 1); Transaction.commit(); } catch (InterruptedException e) { } } } public static void main(String[] args) throws InterruptedException { TopLevelA A = new TopLevelA(); TopLevelZ Z = new TopLevelZ(); A.start(); Z.start(); A.join(); Z.join(); if (x.get() != 1) { throw new AssertionError("Check in the end verified that x != 1"); } if (y.get() != 0) { throw new AssertionError("Check in the end verified that y != 0"); } System.out.println("Successful test"); } }