package jvstm.test.point.runners;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import jvstm.CommitException;
import jvstm.SuspendedTransaction;
import jvstm.Transaction;
import jvstm.test.point.core.Point;
public class RunRwWithRwConflictDisjointFields{
private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
public static <T extends Number> void performTest(final Point<T> p) throws Exception{
final long initX = p.getX().longValue();
final long initY = p.getY().longValue();
final Transaction rwTrx1 = Transaction.begin(false);
SuspendedTransaction r1 = rwTrx1.suspendTx();
//
// ThreadLocal -> rwTrx2
//
final Transaction rwTrx2 = Transaction.begin(false);
Assert.assertEquals(initY, p.getY().longValue());
p.setY(update(initY));
Assert.assertEquals(update(initY), p.getY().longValue());
final SuspendedTransaction r2Token = rwTrx2.suspendTx();
//
// ThreadLocal -> rwTrx1
//
rwTrx1.resume(r1);
long currX = p.getX().longValue();
Assert.assertEquals(initX, currX);
p.setX(update(initX));
Assert.assertEquals(update(initX), p.getX().longValue());
final SuspendedTransaction r1Token = rwTrx1.suspendTx();
//
// Main thread starts a new transaction
//
currX = p.getX().longValue();
long currY = p.getY().longValue();
Assert.assertEquals(initX, currX);
Assert.assertEquals(initY, currY);
//
// ThreadLocal -> rwTrx2
//
final Future<?> fT2 = executor.submit(new Runnable() { public void run() {
rwTrx2.resume(r2Token);
Transaction.commit();
//
// Starts a new transaction
//
long currX = p.getX().longValue();
long currY = p.getY().longValue();
Assert.assertEquals(initX, currX);
Assert.assertEquals(update(initY), currY);
}});
//
// ThreadLocal -> rwTrx1
//
final Future<?> fT1 = executor.schedule(new Runnable() { public void run() {
rwTrx1.resume(r1Token);
long currX = p.getX().longValue();
Assert.assertEquals(update(initX), currX);
try{
Transaction.commit(); // The commit succeeds with conflict detection granularity of word-level
Assert.assertTrue(false); // Fields with different VBoxes will not conflict
}catch(CommitException e){
Assert.assertTrue(true);
rwTrx1.abortTx();
}
}}, 1000, TimeUnit.MILLISECONDS);
fT2.get();
fT1.get();
//
// Main thread starts a new transaction
//
Assert.assertEquals(initX, p.getX().longValue());
Assert.assertEquals(update(initY), p.getY().longValue());
}
private static long update(long src){
return (src*4+6)/2;
}
}