package org.deuce.transaction.tl2;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.deuce.transaction.TransactionException;
import org.deuce.transaction.tl2.field.BooleanWriteFieldAccess;
import org.deuce.transaction.tl2.field.ByteWriteFieldAccess;
import org.deuce.transaction.tl2.field.CharWriteFieldAccess;
import org.deuce.transaction.tl2.field.DoubleWriteFieldAccess;
import org.deuce.transaction.tl2.field.FloatWriteFieldAccess;
import org.deuce.transaction.tl2.field.IntWriteFieldAccess;
import org.deuce.transaction.tl2.field.LongWriteFieldAccess;
import org.deuce.transaction.tl2.field.ObjectWriteFieldAccess;
import org.deuce.transaction.tl2.field.ReadFieldAccess;
import org.deuce.transaction.tl2.field.ShortWriteFieldAccess;
import org.deuce.transaction.tl2.field.WriteFieldAccess;
import org.deuce.transaction.tl2.pool.Pool;
import org.deuce.transaction.tl2.pool.ResourceFactory;
import org.deuce.transform.Exclude;
import org.deuce.trove.TObjectProcedure;
/**
* TL2 implementation
*
* @author Guy Korland
* @since 1.0
*/
@Exclude
final public class Context implements org.deuce.transaction.Context {
final static AtomicInteger clock = new AtomicInteger(0);
final private ReadSet readSet = new ReadSet();
final private WriteSet writeSet = new WriteSet();
private ReadFieldAccess currentReadFieldAccess = null;
// Used by the thread to mark locks it holds.
final private byte[] locksMarker = new byte[LockTable.LOCKS_SIZE / 8 + 1];
final private LockProcedure lockProcedure = new LockProcedure(locksMarker);
// Marked on beforeRead, used for the double lock check
private int localClock;
private int lastReadLock;
// Global lock used to allow only one irrevocable transaction solely.
// final private static ReentrantReadWriteLock irrevocableAccessLock = new
// ReentrantReadWriteLock();
// private boolean irrevocableState = false;
final private TObjectProcedure<WriteFieldAccess> putProcedure = new TObjectProcedure<WriteFieldAccess>() {
@Override
public boolean execute(WriteFieldAccess writeField) {
writeField.put();
return true;
}
};
public Context() {
this.localClock = clock.get();
}
@Override
public void init(int atomicBlockId, String metainf) {
this.currentReadFieldAccess = null;
this.readSet.clear();
this.writeSet.clear();
this.objectPool.clear();
this.booleanPool.clear();
this.bytePool.clear();
this.charPool.clear();
this.shortPool.clear();
this.intPool.clear();
this.longPool.clear();
this.floatPool.clear();
this.doublePool.clear();
// Lock according to the transaction irrevocable state
// if (irrevocableState)
// irrevocableAccessLock.writeLock().lock();
// else
// irrevocableAccessLock.readLock().lock();
this.localClock = clock.get();
}
@Override
public boolean commit() {
// try {
if (writeSet.isEmpty()) // if the writeSet is empty no need to lock
// a thing.
return true;
try {
// pre commit validation phase
writeSet.forEach(lockProcedure);
readSet.checkClock(localClock, locksMarker);
} catch (TransactionException exception) {
lockProcedure.unlockAll();
return false;
}
// commit new values and release locks
writeSet.forEach(putProcedure);
lockProcedure.setAndUnlockAll();
return true;
// } finally {
// if (irrevocableState) {
// irrevocableState = false;
// irrevocableAccessLock.writeLock().unlock();
// } else {
// irrevocableAccessLock.readLock().unlock();
// }
// }
}
@Override
public void rollback() {
// irrevocableAccessLock.readLock().unlock();
}
private WriteFieldAccess onReadAccess0(Object obj, long field) {
ReadFieldAccess current = currentReadFieldAccess;
int hash = current.hashCode();
// Check the read is still valid
LockTable.checkLock(hash, localClock, lastReadLock);
// Check if it is already included in the write set
return writeSet.contains(current);
}
private void addWriteAccess0(WriteFieldAccess write) {
// Add to write set
writeSet.put(write);
}
@Override
public void beforeReadAccess(Object obj, long field) {
ReadFieldAccess next = readSet.getNext();
currentReadFieldAccess = next;
next.init(obj, field);
// Check the read is still valid
lastReadLock = LockTable.checkLock(next.hashCode(), localClock);
}
@Override
public Object onReadAccess(Object obj, Object value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((ObjectWriteFieldAccess) writeAccess).getValue();
}
@Override
public boolean onReadAccess(Object obj, boolean value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((BooleanWriteFieldAccess) writeAccess).getValue();
}
@Override
public byte onReadAccess(Object obj, byte value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((ByteWriteFieldAccess) writeAccess).getValue();
}
@Override
public char onReadAccess(Object obj, char value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((CharWriteFieldAccess) writeAccess).getValue();
}
@Override
public short onReadAccess(Object obj, short value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((ShortWriteFieldAccess) writeAccess).getValue();
}
@Override
public int onReadAccess(Object obj, int value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((IntWriteFieldAccess) writeAccess).getValue();
}
@Override
public long onReadAccess(Object obj, long value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((LongWriteFieldAccess) writeAccess).getValue();
}
@Override
public float onReadAccess(Object obj, float value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((FloatWriteFieldAccess) writeAccess).getValue();
}
@Override
public double onReadAccess(Object obj, double value, long field) {
WriteFieldAccess writeAccess = onReadAccess0(obj, field);
if (writeAccess == null)
return value;
return ((DoubleWriteFieldAccess) writeAccess).getValue();
}
@Override
public void onWriteAccess(Object obj, Object value, long field) {
ObjectWriteFieldAccess next = objectPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, boolean value, long field) {
BooleanWriteFieldAccess next = booleanPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, byte value, long field) {
ByteWriteFieldAccess next = bytePool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, char value, long field) {
CharWriteFieldAccess next = charPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, short value, long field) {
ShortWriteFieldAccess next = shortPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, int value, long field) {
IntWriteFieldAccess next = intPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, long value, long field) {
LongWriteFieldAccess next = longPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, float value, long field) {
FloatWriteFieldAccess next = floatPool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
@Override
public void onWriteAccess(Object obj, double value, long field) {
DoubleWriteFieldAccess next = doublePool.getNext();
next.set(value, obj, field);
addWriteAccess0(next);
}
private static class ObjectResourceFactory implements
ResourceFactory<ObjectWriteFieldAccess> {
@Override
public ObjectWriteFieldAccess newInstance() {
return new ObjectWriteFieldAccess();
}
}
final private Pool<ObjectWriteFieldAccess> objectPool = new Pool<ObjectWriteFieldAccess>(
new ObjectResourceFactory());
private static class BooleanResourceFactory implements
ResourceFactory<BooleanWriteFieldAccess> {
@Override
public BooleanWriteFieldAccess newInstance() {
return new BooleanWriteFieldAccess();
}
}
final private Pool<BooleanWriteFieldAccess> booleanPool = new Pool<BooleanWriteFieldAccess>(
new BooleanResourceFactory());
private static class ByteResourceFactory implements
ResourceFactory<ByteWriteFieldAccess> {
@Override
public ByteWriteFieldAccess newInstance() {
return new ByteWriteFieldAccess();
}
}
final private Pool<ByteWriteFieldAccess> bytePool = new Pool<ByteWriteFieldAccess>(
new ByteResourceFactory());
private static class CharResourceFactory implements
ResourceFactory<CharWriteFieldAccess> {
@Override
public CharWriteFieldAccess newInstance() {
return new CharWriteFieldAccess();
}
}
final private Pool<CharWriteFieldAccess> charPool = new Pool<CharWriteFieldAccess>(
new CharResourceFactory());
private static class ShortResourceFactory implements
ResourceFactory<ShortWriteFieldAccess> {
@Override
public ShortWriteFieldAccess newInstance() {
return new ShortWriteFieldAccess();
}
}
final private Pool<ShortWriteFieldAccess> shortPool = new Pool<ShortWriteFieldAccess>(
new ShortResourceFactory());
private static class IntResourceFactory implements
ResourceFactory<IntWriteFieldAccess> {
@Override
public IntWriteFieldAccess newInstance() {
return new IntWriteFieldAccess();
}
}
final private Pool<IntWriteFieldAccess> intPool = new Pool<IntWriteFieldAccess>(
new IntResourceFactory());
private static class LongResourceFactory implements
ResourceFactory<LongWriteFieldAccess> {
@Override
public LongWriteFieldAccess newInstance() {
return new LongWriteFieldAccess();
}
}
final private Pool<LongWriteFieldAccess> longPool = new Pool<LongWriteFieldAccess>(
new LongResourceFactory());
private static class FloatResourceFactory implements
ResourceFactory<FloatWriteFieldAccess> {
@Override
public FloatWriteFieldAccess newInstance() {
return new FloatWriteFieldAccess();
}
}
final private Pool<FloatWriteFieldAccess> floatPool = new Pool<FloatWriteFieldAccess>(
new FloatResourceFactory());
private static class DoubleResourceFactory implements
ResourceFactory<DoubleWriteFieldAccess> {
@Override
public DoubleWriteFieldAccess newInstance() {
return new DoubleWriteFieldAccess();
}
}
final private Pool<DoubleWriteFieldAccess> doublePool = new Pool<DoubleWriteFieldAccess>(
new DoubleResourceFactory());
// @Override
// public void onIrrevocableAccess() {
// if(irrevocableState) // already in irrevocable state so no need to
// restart transaction.
// return;
//
// irrevocableState = true;
// throw TransactionException.STATIC_TRANSACTION;
// }
@Override
public void beforeReadAccessStrongIso(Object obj, long field, Object obj2,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, Object value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, boolean value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, byte value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, char value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, short value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, int value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, long value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, float value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
@Override
public void onWriteAccessStrongIso(Object obj, double value, long field,
long fieldObj) {
System.out.println("ERROR STRONG ISO NOT IMPLEMENTED");
}
}