Package org.deuce.transaction.tl2cm

Source Code of org.deuce.transaction.tl2cm.Context

package org.deuce.transaction.tl2cm;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.deuce.transaction.TransactionException;
import org.deuce.transaction.tl2cm.cm.ContentionManager;
import org.deuce.transaction.tl2cm.cm.ContentionManager.Action;
import org.deuce.transaction.tl2cm.contexts.ContextsMap;
import org.deuce.transaction.tl2.WriteSet;
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 edu.vt.realtime.Timespec;

/**
* Context class for TL2 STM with Contention Management support. This class queries its
* Contention Manager regarding the need for bookkeeping of shared information, like
* priorities, currently running transaction, etc.
*
* Based on Guy Korland's and Pascal Felber's work on <code>org.deuce.transaction.tl2.*</code>
* and <code>org.deuce.transaction.lsa*</code>
* @author Yoav Cohen, yoav.cohen@cs.tau.ac.il
*/
@Exclude
final public class Context extends org.deuce.transaction.AbstractContext {

  public static final String TL2CM_LOGGER = "org.deuce.transaction.tl2cm";
  //private static final Logger logger = Logger.getLogger(TL2CM_LOGGER);
  //private static final boolean isTracing = logger.isLoggable(Level.INFO);
  private static final AtomicInteger clock = new AtomicInteger(0);
  private static final AtomicInteger threadIdCounter = new AtomicInteger(LockTable.INITIAL_OWNER+1);
  private static final ContextsMap threads = Factory.createContextsMap();
  private static ContentionManager cm;
 
  private final int threadId;
  private final ReadSet readSet = new ReadSet();
  private final WriteSet writeSet = new WriteSet();
  private final Statistics stats = new Statistics();
  private final AtomicInteger localClock;
  private final AtomicReference<Status> status;
  private final AtomicInteger priority = new AtomicInteger(0);
  private final AtomicInteger timestamp = new AtomicInteger(0);
  private int atomicBlockId;
  private long lastReadLock;
 
  static {
    try {
      System.out.println("TL2CM Initialized:");
      cm = Factory.createContentionManager();
      System.out.println("Contention Manager: " + cm.getClass().getSimpleName() + "\n");
    }
    catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }
  }
 
  public Context() {
    this.threadId = threadIdCounter.getAndIncrement();
    this.localClock = new AtomicInteger(0);
    this.status = new AtomicReference<Status>(Status.COMMITTED);
    threads.put(threadId, this);
  }
 
  @Override
  protected void finalize() throws Throwable {
     //threads.remove(threadId);
     super.finalize();
  }
 
  public void init(int atomicBlockId) {
    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();
    this.atomicBlockId = atomicBlockId;
    this.localClock.set(clock.get());
    if (cm.requiresTimestamps() && status.get().equals(Status.COMMITTED)) {
      // Only if the last transaction committed we issue a new timestamp
      // otherwise we continue with the old one
      this.timestamp.set(localClock.get());
    }
    this.status.set(Status.RUNNING);
    this.stats.starts++;
  }

  public boolean commit() {
    //trace("Commit begin", null);
    if (writeSet.isEmpty()) {
      // if the writeSet is empty no need to lock a thing - all read locations
      // were validated before we read them
      //trace("Commit end | result = true (writeSet empty)", null);
      this.stats.commits++;
      return true;
    }
   
    // Lock write set
    int lockedCounter = 0;
    for (WriteFieldAccess writeField : writeSet) {
      //trace("trying to acquire lock #{0}", new Object[]{lockedCounter});
      while (status.get().equals(Status.RUNNING)) {
        int lockOwner = LockTable.lock(writeField.hashCode(), threadId);
        if (lockOwner == -1) {
          // Lock appeared to be free, but when I tried to CAS it, I failed.
          // The owner of the lock is not known to me, therefore I can't
          // efficiently do contention management, so I just retry.
          continue;
        }
        else if (threadId != lockOwner) { 
          // Lock is owned by some other thread. Contention Management is in order
          Context otherCtx = threads.get(lockOwner);
          if (otherCtx == null) {
            // this can happen if the other thread already finished and
            // un-registered its context object. In this case, I retry.
            //trace("Lock owner is not available, probably already finished. Retrying lock #{0}", new Object[]{lockedCounter});
            continue;
          }
          else {
            Action action = cm.resolve(writeField, this, otherCtx);
            if (action == Action.RESTART) {
              // this will cause my transaction to roll-back and restart itself
              //trace("restarting transaction as a result of contention on lock #{0}", new Object[]{lockedCounter});
              kill(-1);
              break;
            }
            else if (action == Action.RETRY_LOCK) {
              // try again to acquire the lock
              //trace("Retrying lock #{0}", new Object[]{lockedCounter});
              continue;
            }
          }
        }
        else {
          // Lock is acquired!
          //trace("Lock #{0} acquired", new Object[]{lockedCounter});
          if (cm.requiresPriorities()) {
            priority.incrementAndGet();
          }
          lockedCounter++;
          break;
        }
      }
      // If the while loop ended because someone killed me
      // don't go to the next lock
      if (!status.get().equals(Status.RUNNING)) {
        break;
      }
    }
    // If the write set is locked, validate read set
    boolean readSetValidated = false;
    if (status.get().equals(Status.RUNNING)) {
      try {
        readSet.checkClock(localClock.get());
        readSetValidated = true;
      }
      catch (TransactionException e) {
        //trace("Commit | read set not validated", null);
      }
    }
    // Wrap things up - try to commit
    boolean committed = false;
    if (readSetValidated) {
      // If the read set is validated we can update the locks with a new version
      int newClock = clock.incrementAndGet();
      //trace("new clock is {0}", new Object[]{newClock});
      for (WriteFieldAccess writeField : writeSet) {
        writeField.put(); // commit value to field
        LockTable.setAndReleaseLock(writeField.hashCode(), newClock, threadId);
      }
      //trace("Commit end | result = true", null);
      if (cm.requiresPriorities()) {
        priority.set(0);
      }
      committed = status.compareAndSet(Status.RUNNING, Status.COMMITTED);
      if (committed) {
        this.stats.commits++;
        return true;
      }
    }
   
    // Could not commit - rollback
    if (!readSetValidated || !committed) {
      rollback(lockedCounter);
      //trace("Commit end | result = false", null);
      return false;
    }
    return false;
  }

  public boolean commit(Timespec deadline_ts, Timespec period_ts, int tid) {
    // dummy implementation to accomodate dtl2realtime
    return true;
  }
 
  public boolean abort() {
    // Proxy method implemented - For real implementation -come later - Sachin
    return true;
 
 
  public boolean rollback() {
    return true;
  }
 
  /**
   * Kills the transaction executed by this thread. This method only kills
   * the transaction that caused conflict by checking that the local clock
   * value at the time the method was invoked equals the local clock value
   * at the time the method is run.
   * @param timeOfKill local clock at the time the kill or -1 if this thread kills itself
   * method was invoked
   */
  public void kill(int timeOfKill) {
    if (timeOfKill == -1 || localClock.get() == timeOfKill) {
      //trace("kill", null);
      status.compareAndSet(Status.RUNNING, Status.ABORTED);
    }
  }
 
  /**
   * Gets the Id of this thread
   * @return Id of this thread
   */
  public int getThreadId() {
    return threadId;
  }

  public Status getStatus() {
    return status.get();
  }
 
  public void setStatus(Status status) {
    this.status.set(status);
  }

  /**
   * Gets the clock value of the current transaction
   * @return clock value of the current transaction
   */
  public int getLocalClock() {
    return localClock.get();
  }
 
  /**
   * Gets the timestamp of the current transaction. The timestamp
   * of the current transaction is the local clock value of the
   * first attempt made by this thread to execute the current
   * transaction.
   * @return timestamp of the current transaction
   */
  public int getTimestamp() {
    return timestamp.get();
  }

  /**
   * Gets the priority of this thread. The priority
   * is calculated based on the number of locks this
   * thread has opened and not committed on.
   * @return thread's priority
   */
  public int getPriority() {
    return priority.get();
  }

  public Statistics getStatistics() {
    return this.stats;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append(" TID=");
    sb.append(threadId);
    sb.append(", TX=");
    sb.append(atomicBlockId);
    sb.append(", localClock=");
    sb.append(localClock);
    sb.append(", globalClock=");
    sb.append(clock.get());
    sb.append(" writeSet=");
    sb.append(writeSet.size());
    if (cm.requiresPriorities()) {
      sb.append(", priority=");
      sb.append(priority.get());
    }
    String str = sb.toString();
    return str;
  }

  /**
   * Rolls back the transaction by releasing the locations acquired
   * so far during the <code>commit</code> method
   * @param locksCounter amount of locked locations
   */
  private void rollback(int locksCounter) {
    for (WriteFieldAccess writeField : writeSet) {
      if (locksCounter-- > 0) {
        LockTable.unLock(writeField.hashCode());
      }
    }
  }
 
//  private void trace(String message, Object[] params) {
//    if (isTracing) {
//      StringBuilder sb = new StringBuilder(message);
//      sb.append(this.toString());
//      String str = sb.toString();
//      logger.log(Level.INFO, str, params);
//    }
//  }

  private WriteFieldAccess onReadAccess0(Object obj, long field) {
    ReadFieldAccess current = readSet.getCurrent();
    int hash = current.hashCode();
    // Check the read is still valid
    LockTable.checkLock(hash, localClock.get(), lastReadLock);
    // Check if it is already included in the write set
    return writeSet.contains(current);
  }

  private void addWriteAccess0(WriteFieldAccess write) {
    //trace("adding write to hash={0}", new Object[]{write.hashCode()});
    // Add to write set
    writeSet.put(write);
  }

  public void beforeReadAccess(Object obj, long field) {
    ReadFieldAccess next = readSet.getNext();
    next.init(obj, field);
    // Check the read is still valid
    lastReadLock = LockTable.checkAndGetLock(next.hashCode(), localClock.get());
  }

  public Object onReadAccess(Object obj, Object value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((ObjectWriteFieldAccess) writeAccess).getValue();
  }

  public boolean onReadAccess(Object obj, boolean value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((BooleanWriteFieldAccess) writeAccess).getValue();
  }

  public byte onReadAccess(Object obj, byte value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((ByteWriteFieldAccess) writeAccess).getValue();
  }

  public char onReadAccess(Object obj, char value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((CharWriteFieldAccess) writeAccess).getValue();
  }

  public short onReadAccess(Object obj, short value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((ShortWriteFieldAccess) writeAccess).getValue();

  }

  public int onReadAccess(Object obj, int value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((IntWriteFieldAccess) writeAccess).getValue();
  }

  public long onReadAccess(Object obj, long value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((LongWriteFieldAccess) writeAccess).getValue();
  }

  public float onReadAccess(Object obj, float value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((FloatWriteFieldAccess) writeAccess).getValue();
  }

  public double onReadAccess(Object obj, double value, long field) {
    WriteFieldAccess writeAccess = onReadAccess0(obj, field);
    if (writeAccess == null)
      return value;

    return ((DoubleWriteFieldAccess) writeAccess).getValue();
  }

  public void onWriteAccess(Object obj, Object value, long field) {
    ObjectWriteFieldAccess next = objectPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, boolean value, long field) {

    BooleanWriteFieldAccess next = booleanPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, byte value, long field) {

    ByteWriteFieldAccess next = bytePool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, char value, long field) {

    CharWriteFieldAccess next = charPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, short value, long field) {

    ShortWriteFieldAccess next = shortPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, int value, long field) {

    IntWriteFieldAccess next = intPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, long value, long field) {

    LongWriteFieldAccess next = longPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, float value, long field) {

    FloatWriteFieldAccess next = floatPool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  public void onWriteAccess(Object obj, double value, long field) {

    DoubleWriteFieldAccess next = doublePool.getNext();
    next.set(value, obj, field);
    addWriteAccess0(next);
  }

  private Pool<ObjectWriteFieldAccess> objectPool = new Pool<ObjectWriteFieldAccess>(
      new ResourceFactory<ObjectWriteFieldAccess>() {
        public ObjectWriteFieldAccess newInstance() {
          return new ObjectWriteFieldAccess();
        }
      });

  private Pool<BooleanWriteFieldAccess> booleanPool = new Pool<BooleanWriteFieldAccess>(
      new ResourceFactory<BooleanWriteFieldAccess>() {
        public BooleanWriteFieldAccess newInstance() {
          return new BooleanWriteFieldAccess();
        }
      });

  private Pool<ByteWriteFieldAccess> bytePool = new Pool<ByteWriteFieldAccess>(
      new ResourceFactory<ByteWriteFieldAccess>() {
        public ByteWriteFieldAccess newInstance() {
          return new ByteWriteFieldAccess();
        }
      });

  private Pool<CharWriteFieldAccess> charPool = new Pool<CharWriteFieldAccess>(
      new ResourceFactory<CharWriteFieldAccess>() {
        public CharWriteFieldAccess newInstance() {
          return new CharWriteFieldAccess();
        }
      });

  private Pool<ShortWriteFieldAccess> shortPool = new Pool<ShortWriteFieldAccess>(
      new ResourceFactory<ShortWriteFieldAccess>() {
        public ShortWriteFieldAccess newInstance() {
          return new ShortWriteFieldAccess();
        }
      });

  private Pool<IntWriteFieldAccess> intPool = new Pool<IntWriteFieldAccess>(
      new ResourceFactory<IntWriteFieldAccess>() {
        public IntWriteFieldAccess newInstance() {
          return new IntWriteFieldAccess();
        }
      });

  private Pool<LongWriteFieldAccess> longPool = new Pool<LongWriteFieldAccess>(
      new ResourceFactory<LongWriteFieldAccess>() {
        public LongWriteFieldAccess newInstance() {
          return new LongWriteFieldAccess();
        }
      });

  private Pool<FloatWriteFieldAccess> floatPool = new Pool<FloatWriteFieldAccess>(
      new ResourceFactory<FloatWriteFieldAccess>() {
        public FloatWriteFieldAccess newInstance() {
          return new FloatWriteFieldAccess();
        }
      });

  private Pool<DoubleWriteFieldAccess> doublePool = new Pool<DoubleWriteFieldAccess>(
      new ResourceFactory<DoubleWriteFieldAccess>() {
        public DoubleWriteFieldAccess newInstance() {
          return new DoubleWriteFieldAccess();
        }
      });

  @Override
  public boolean wakeupWaitingTasks(int tid) {
    // TODO Auto-generated method stub
    return false;
  }

  @Override
  public boolean abort(int tid) {
    // TODO Auto-generated method stub
    return false;
  }

}
TOP

Related Classes of org.deuce.transaction.tl2cm.Context

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.