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 RunRwWithRwConflictSameFields{
private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
public static <T extends Number> void performTest(final Point<T> p) throws Exception{
p.setX(13);
p.setY(14);
final long initX = p.getX().longValue();
final long initY = p.getY().longValue();
final Transaction rwTrx1 = Transaction.begin(false);
SuspendedTransaction r1Token = rwTrx1.suspendTx();
//
// ThreadLocal -> rwTrx2
//
final Transaction rwTrx2 = Transaction.begin(false);
Assert.assertEquals(initX, p.getX().longValue());
Assert.assertEquals(initY, p.getY().longValue());
p.setX(update(initX));
p.setY(update(initY));
Assert.assertEquals(update(initX), p.getX().longValue());
Assert.assertEquals(update(initY), p.getY().longValue());
final SuspendedTransaction r2Token = rwTrx2.suspendTx();
//
// ThreadLocal -> rwTrx1 -> this transaction will exchange
// the values of x and y.
//
rwTrx1.resume(r1Token);
long currX = p.getX().longValue();
Assert.assertEquals(initX, currX);
Assert.assertEquals(initY, p.getY().longValue());
p.setX(initY);
p.setY(initX);
Assert.assertEquals(initY, p.getX().longValue());
Assert.assertEquals(initX, p.getY().longValue());
final SuspendedTransaction r1TokenB = 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();
}});
//
// ThreadLocal -> rwTrx1
//
Future<?> fT1 = executor.schedule(new Runnable() { public void run() {
rwTrx1.resume(r1TokenB);
try {
Transaction.commit();
} catch (CommitException e) {
Assert.assertTrue(true);
rwTrx1.abortTx();
//
// ThreadLocal -> rwTrx1 -> restart a new transaction
// that will try to exchange the values of x and y.
//
try {fT2.get();}
catch (Exception e2) {throw new RuntimeException(e2);}
Transaction.begin(false);
long currX = p.getX().longValue();
long currY = p.getY().longValue();
Assert.assertEquals(update(initX), currX);
Assert.assertEquals(update(initY), currY);
p.setX(update(initY));
p.setY(update(initX));
Assert.assertEquals(update(initY), p.getX().longValue());
Assert.assertEquals(update(initX), p.getY().longValue());
Transaction.commit();
//
// Main thread starts a new transaction
//
Assert.assertEquals(update(initY), p.getX().longValue());
Assert.assertEquals(update(initX), p.getY().longValue());
return;
}
Assert.assertTrue(false);
}}, 1000, TimeUnit.MILLISECONDS);
fT2.get();
fT1.get();
//
// Main thread starts a new transaction
//
currX = p.getX().longValue();
currY = p.getY().longValue();
Assert.assertEquals(update(initY), p.getX().longValue());
Assert.assertEquals(update(initX), p.getY().longValue());
}
private static long update(long src){
return (src*4+6)/2;
}
}