import java.util.Random;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
+import java.util.Vector;
public class Executor {
int numThreads;
this(numThreads, numTrans, deltaTrans, numObjects, numAccesses, deltaAccesses, readPercent, delay, deltaDelay, nonTrans, deltaNonTrans, 100, 100, 0);
}
+ public static int readInt(InputStream is) {
+ try {
+ int b1=is.read();
+ int b2=is.read();
+ int b3=is.read();
+ int b4=is.read();
+ int retval=(b1<<24)|(b2<<16)|(b3<<8)|b4;
+ if (retval<0)
+ throw new Error();
+ return retval;
+ } catch (Exception e) {
+ throw new Error();
+ }
+ }
+
+ public static long readLong(InputStream is) {
+ try {
+ long b1=is.read();
+ long b2=is.read();
+ long b3=is.read();
+ long b4=is.read();
+ long b5=is.read();
+ long b6=is.read();
+ long b7=is.read();
+ long b8=is.read();
+ long retval=(b1<<56)|(b2<<48)|(b3<<40)|(b4<<32)|
+ (b5<<24)|(b6<<16)|(b7<<8)|b8;
+ if (retval<0)
+ throw new Error();
+ return retval;
+ } catch (Exception e) {
+ throw new Error();
+ }
+ }
+
+ public Executor(String filename) {
+ BufferedInputStream bir;
+ try {
+ bir=new BufferedInputStream(new FileInputStream(filename));
+ } catch (Exception e) {
+ throw new Error();
+ }
+ numThreads=readInt(bir);
+ threads=new ThreadClass[numThreads];
+ long earliest=-1;
+ for(int i=0;i<numThreads;i++) {
+ threads[i]=readThread(bir);
+ long inittime=threads[i].trans[0].getTime(0);
+ if (earliest==-1||earliest>inittime) {
+ earliest=inittime;
+ }
+ }
+ for(int i=0;i<numThreads;i++) {
+ long inittime=threads[i].trans[0].getTime(0);
+ assert(threads[i].trans[0].numEvents()==1);
+ threads[i].trans[0].setTime(0, inittime-earliest);
+ }
+ }
+
+ public static final int EV_THREAD=0;
+ public static final int EV_ENTERBARRIER=1;
+ public static final int EV_READ=2;
+ public static final int EV_WRITE=3;
+ public static final int EV_START=4;
+ public static final int EV_COMMIT=5;
+ public static final int EV_ABORT=6;
+ public static final int EV_ARRAYREAD=7;
+ public static final int EV_ARRAYWRITE=8;
+ public static final int EV_EXITBARRIER=9;
+
+ private Transaction createTransaction(Vector<TEvent> v) {
+ Transaction t=new Transaction(v.size());
+ for(int i=0;i<v.size();i++) {
+ TEvent e=v.get(i);
+ t.setTime(i,e.time);
+ t.setEvent(i,e.type);
+ t.setObject(i,e.oid);
+ t.setIndex(i,e.index);
+ }
+ return t;
+ }
+
+ private ThreadClass readThread(InputStream is) {
+ int numEvents=readInt(is);
+ Vector<Transaction> transactions=new Vector<Transaction>();
+ Vector<TEvent> currtrans=null;
+ long starttime=-1;
+ long lasttime=0;
+ long firsttime=-1;
+ for(int i=0;i<numEvents;i++) {
+ int eventType=readInt(is);
+ int object=-1;
+ int index=-1;
+ switch(eventType) {
+ case EV_READ:
+ case EV_WRITE:
+ object=readInt(is);
+ break;
+ case EV_ARRAYREAD:
+ case EV_ARRAYWRITE:
+ object=readInt(is);
+ index=readInt(is);
+ break;
+ default:
+ break;
+ }
+ long time=readLong(is);
+ //create dummy first transaction
+ if (firsttime==-1) {
+ Transaction t=new Transaction(1);
+ t.setTime(0, time);
+ t.setObject(0, -1);
+ t.setIndex(0, -1);
+ transactions.add(t);
+ firsttime=time;
+ }
+ //have read all data in
+ switch(eventType) {
+ case EV_START:
+ starttime=time;
+ currtrans=new Vector<TEvent>();
+ if (lasttime!=-1) {
+ Transaction t=new Transaction(1);
+ t.setEvent(0, Transaction.DELAY);
+ t.setTime(0, time-lasttime);
+ t.setObject(0, -1);
+ t.setIndex(0, -1);
+ transactions.add(t);
+ }
+ break;
+ case EV_READ:
+ case EV_ARRAYREAD: {
+ long delta=time-starttime;
+ TEvent ev=new TEvent(Transaction.READ, delta, object, index);
+ currtrans.add(ev);
+ }
+ break;
+ case EV_WRITE:
+ case EV_ARRAYWRITE: {
+ long delta=time-starttime;
+ TEvent ev=new TEvent(Transaction.WRITE, delta, object, index);
+ currtrans.add(ev);
+ }
+ break;
+ case EV_COMMIT: {
+ long delta=time-starttime;
+ TEvent ev=new TEvent(Transaction.DELAY, delta);
+ currtrans.add(ev);
+ lasttime=time;
+ transactions.add(createTransaction(currtrans));
+ }
+ break;
+ case EV_ABORT:
+ //No need to generate new delay transaction
+ lasttime=-1;
+ break;
+ case EV_THREAD:
+ //No need to do anything
+ break;
+ case EV_ENTERBARRIER: {
+ //Barrier
+ if (lasttime!=-1) {
+ Transaction t=new Transaction(1);
+ t.setEvent(0, Transaction.DELAY);
+ t.setTime(0, time-lasttime);
+ t.setObject(0, -1);
+ t.setIndex(0, -1);
+ transactions.add(t);
+ }
+ transactions.add(Transaction.getBarrier());
+ }
+ break;
+ case EV_EXITBARRIER: {
+ //Barrier
+ lasttime=time;
+ }
+ break;
+ }
+ }
+ ThreadClass tc=new ThreadClass(transactions.size());
+ for(int i=0;i<transactions.size();i++) {
+ tc.setTransaction(i,transactions.get(i));
+ }
+ return tc;
+ }
+
public Executor(int numThreads, int numTrans, int deltaTrans, int numObjects, int numAccesses, int deltaAccesses, int readPercent, int delay, int deltaDelay, int nonTrans, int deltaNonTrans, int splitobjects, int splitaccesses, int readPercentSecond) {
this.numThreads=numThreads;
this.numTrans=numTrans;
int abortRatio;
int deadlockcount;
int checkdepth;
+ int barriercount;
public FlexScheduler(Executor e, int policy, int abortThreshold, int abortRatio, int checkdepth, Plot p) {
this(e, policy, p);
public FlexScheduler(Executor e, int policy, Plot p) {
this.e=e;
+ barriercount=e.numThreads();
aborted=new boolean[e.numThreads()];
currentevents=new Event[e.numThreads()];
rdobjmap=new Hashtable();
PriorityQueue eq;
int policy;
boolean[] aborted;
- int shorttesttime;
+ long shorttesttime;
Hashtable rdobjmap;
Hashtable wrobjmap;
int abortcount;
return commitcount;
}
- public int getTime() {
+ public long getTime() {
return shorttesttime;
}
//Aborts another thread...
- public void reschedule(int currthread, int time) {
+ public void reschedule(int currthread, long time) {
currentevents[currthread].makeInvalid();
if (threadinfo[currthread].isStalled()) {
//remove from waiter list
threadinfo[currthread].setStall(false);
- getmapping(threadinfo[currthread].getObject()).getWaiters().remove(currentevents[currthread]);
+ getmapping(threadinfo[currthread].getObjIndex()).getWaiters().remove(currentevents[currthread]);
}
if (serAbort!=null) {
serAbort.addPoint(time, currthread);
}
- private void releaseObjects(Transaction trans, int currthread, int time) {
+ private void releaseObjects(Transaction trans, int currthread, long time) {
//remove all events
for(int i=0;i<trans.numEvents();i++) {
- int object=trans.getObject(i);
- Integer obj=new Integer(object);
- if (object!=-1&&rdobjmap.containsKey(obj)) {
- ((Set)rdobjmap.get(obj)).remove(new Integer(currthread));
+ ObjIndex object=trans.getObjIndex(i);
+
+ if (object!=null&&rdobjmap.containsKey(object)) {
+ ((Set)rdobjmap.get(object)).remove(new Integer(currthread));
}
- if (object!=-1&&wrobjmap.containsKey(obj)) {
- ((Set)wrobjmap.get(obj)).remove(new Integer(currthread));
+ if (object!=null&&wrobjmap.containsKey(object)) {
+ ((Set)wrobjmap.get(object)).remove(new Integer(currthread));
}
- if (object!=-1&&objtoinfo.containsKey(obj)) {
- ObjectInfo oi=(ObjectInfo)objtoinfo.get(obj);
+ if (object!=null&&objtoinfo.containsKey(object)) {
+ ObjectInfo oi=(ObjectInfo)objtoinfo.get(object);
if (oi.getOwner()==currentevents[currthread].getThread()) {
oi.releaseOwner();
public void startinitial() {
for(int i=0;i<e.numThreads();i++) {
Transaction trans=e.getThread(i).getTransaction(0);
- int time=trans.getTime(0);
+ long time=trans.getTime(0);
Event ev=new Event(time, trans, 0, i, 0);
currentevents[i]=ev;
eq.add(ev);
}
public void dosim() {
- int lasttime=0;
+ long lasttime=0;
//start first transactions
startinitial();
Transaction trans=ev.getTransaction();
int event=ev.getEvent();
- int currtime=ev.getTime();
+ long currtime=ev.getTime();
lasttime=currtime;
if (trans.numEvents()==(event+1)) {
p.close();
}
- private ObjectInfo getmapping(int object) {
- Integer obj=new Integer(object);
+ private ObjectInfo getmapping(ObjIndex obj) {
if (!objtoinfo.containsKey(obj))
objtoinfo.put(obj, new ObjectInfo(this));
return (ObjectInfo)objtoinfo.get(obj);
public void tryCommit(Event ev, Transaction trans) {
//ready to commit this one
- int currtime=ev.getTime();
+ long currtime=ev.getTime();
releaseObjects(trans, ev.getThread(), currtime);
//See if we have been flagged as aborted for the lazy case
//abort the other threads
for(int i=0;i<trans.numEvents();i++) {
- int object=trans.getObject(i);
+ ObjIndex object=trans.getObjIndex(i);
int op=trans.getEvent(i);
//Mark commits to objects
if (isLock()&&(op==Transaction.WRITE||op==Transaction.READ)) {
//Check for threads we might cause to abort
if (op==Transaction.WRITE) {
HashSet abortset=new HashSet();
- Integer obj=new Integer(object);
- if (rdobjmap.containsKey(obj)) {
- for(Iterator it=((Set)rdobjmap.get(obj)).iterator();it.hasNext();) {
+ if (rdobjmap.containsKey(object)) {
+ for(Iterator it=((Set)rdobjmap.get(object)).iterator();it.hasNext();) {
Integer threadid=(Integer)it.next();
abortset.add(threadid);
if (isLock()) {
}
}
}
- if (wrobjmap.containsKey(obj)) {
- for(Iterator it=((Set)wrobjmap.get(obj)).iterator();it.hasNext();) {
+ if (wrobjmap.containsKey(object)) {
+ for(Iterator it=((Set)wrobjmap.get(object)).iterator();it.hasNext();) {
Integer threadid=(Integer)it.next();
abortset.add(threadid);
- if (isLock()&&(!rdobjmap.containsKey(obj)||!((Set)rdobjmap.get(obj)).contains(threadid))) {
+ if (isLock()&&(!rdobjmap.containsKey(object)||!((Set)rdobjmap.get(object)).contains(threadid))) {
//if this object hasn't already cause this thread to
//abort, then flag it as an abort cause
ObjectInfo oi=getmapping(object);
}
}
- public Set rdConflictSet(int thread, int object) {
- Integer obj=new Integer(object);
+ public Set rdConflictSet(int thread, ObjIndex obj) {
if (!wrobjmap.containsKey(obj))
return null;
HashSet conflictset=new HashSet();
return conflictset;
}
- public Set wrConflictSet(int thread, int object) {
- Integer obj=new Integer(object);
-
+ public Set wrConflictSet(int thread, ObjIndex obj) {
HashSet conflictset=new HashSet();
if (rdobjmap.containsKey(obj)) {
for(Iterator it=((Set)rdobjmap.get(obj)).iterator();it.hasNext();) {
//set of threads, and the current time
//Returning false causes current transaction not continue to be scheduled
- public boolean handleConflicts(Event ev, Set threadstokill, int time) {
+ public boolean handleConflicts(Event ev, Set threadstokill, long time) {
if (policy==ATTACK) {
for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
Integer thread=(Integer)thit.next();
abortcount++;
return false;
} else if (policy==KARMA) {
- int opponenttime=0;
+ long opponenttime=0;
for(Iterator thit=threadstokill.iterator();thit.hasNext();) {
Integer thread=(Integer)thit.next();
Event other=currentevents[thread.intValue()];
int eventnum=other.getEvent();
- int otime=other.getTransaction().getTime(other.getEvent());
+ long otime=other.getTransaction().getTime(other.getEvent());
if (otime>opponenttime)
opponenttime=otime;
}
public void enqueueEvent(Event ev, Transaction trans) {
//just enqueue next event
int event=ev.getEvent();
- int currtime=ev.getTime();
- int object=trans.getObject(event);
+ long currtime=ev.getTime();
+ ObjIndex object=trans.getObjIndex(event);
int operation=trans.getEvent(event);
- Integer obj=new Integer(object);
if ((operation==Transaction.READ||operation==Transaction.WRITE)&&isLock()) {
ObjectInfo oi=getmapping(object);
break;
}
//follow one more in depth
- toi=getmapping(threadinfo[toi.getOwner()].getObject());
+ toi=getmapping(threadinfo[toi.getOwner()].getObjIndex());
}
if (!deadlocked) {
//don't wait on stalled threads, we could deadlock
threadinfo[ev.getThread()].setStall(true);
- threadinfo[ev.getThread()].setObject(object);
+ threadinfo[ev.getThread()].setObjIndex(object);
if (serStall!=null)
serStall.addPoint(ev.getTime(),ev.getThread());
oi.addWaiter(ev);
//process the current event
if (operation==Transaction.READ) {
//record read event
- if (!rdobjmap.containsKey(obj))
- rdobjmap.put(obj,new HashSet());
- ((Set)rdobjmap.get(obj)).add(new Integer(ev.getThread()));
+ if (!rdobjmap.containsKey(object))
+ rdobjmap.put(object,new HashSet());
+ ((Set)rdobjmap.get(object)).add(new Integer(ev.getThread()));
if (isEager()) {
//do eager contention management
Set conflicts=rdConflictSet(ev.getThread(), object);
}
} else if (operation==Transaction.WRITE) {
//record write event
- if (!wrobjmap.containsKey(obj))
- wrobjmap.put(obj,new HashSet());
- ((Set)wrobjmap.get(obj)).add(new Integer(ev.getThread()));
+ if (!wrobjmap.containsKey(object))
+ wrobjmap.put(object,new HashSet());
+ ((Set)wrobjmap.get(object)).add(new Integer(ev.getThread()));
if (isEager()) {
Set conflicts=wrConflictSet(ev.getThread(), object);
if (conflicts!=null) {
return;
}
}
+ } else if (operation==Transaction.BARRIER) {
+ barriercount--;
+ if (barriercount==0) {
+ for(int i=0;i<e.numThreads();i++) {
+ //enqueue the next event
+ Event bev=currentevents[i];
+ int bevent=bev.getEvent();
+ long bcurrtime=bev.getTime();
+ Transaction btrans=bev.getTransaction();
+ long deltatime=btrans.getTime(bevent+1)-btrans.getTime(bevent);
+ Event nev=new Event(deltatime+currtime, btrans, bevent+1, bev.getThread(), bev.getTransNum());
+ currentevents[bev.getThread()]=nev;
+ eq.add(nev);
+ }
+ barriercount=e.numThreads();
+ } else {
+ //Do nothing
+ //wait until all threads in barrier
+ }
+ return;
}
//enqueue the next event
- int deltatime=trans.getTime(event+1)-trans.getTime(event);
+ long deltatime=trans.getTime(event+1)-trans.getTime(event);
Event nev=new Event(deltatime+currtime, trans, event+1, ev.getThread(), ev.getTransNum());
currentevents[ev.getThread()]=nev;
eq.add(nev);
class Event implements Comparable {
boolean valid;
- int time;
+ long time;
int num;
Transaction t;
int threadid;
return num;
}
- public int getTime() {
+ public long getTime() {
return time;
}
- public void setTime(int time) {
+ public void setTime(long time) {
this.time=time;
}
return threadid;
}
- public Event(int time, Transaction t, int num, int threadid, int transnum) {
+ public Event(long time, Transaction t, int num, int threadid, int transnum) {
this.time=time;
this.t=t;
this.num=num;
//break ties to allow commits to occur earliest
public int compareTo(Object o) {
Event e=(Event)o;
- int delta=time-e.time;
- if (delta!=0)
- return delta;
+ long delta=time-e.time;
+ if (delta!=0) {
+ if (delta>0)
+ return 1;
+ else
+ return -1;
+ }
if (((getEvent()+1)==getTransaction().numEvents())&&
(e.getEvent()+1)!=e.getTransaction().numEvents())
return -1;
public class Scheduler {
Executor e;
- public Scheduler(Executor e, int time) {
+ public Scheduler(Executor e, long time) {
this.e=e;
schedule=new int[e.numEvents()+1][e.numThreads()];
turn=new int[e.numEvents()];
//give last time an event can be scheduled
- lasttime=new int[e.maxEvents()][e.numThreads()];
-
- schedtime=new int[e.maxEvents()][e.numThreads()];
- lastrd=new int[e.numEvents()+1][e.numObjects()];
- lastwr=new int[e.numEvents()+1][e.numObjects()];
+ lasttime=new long[e.maxEvents()][e.numThreads()];
+ schedtime=new long[e.maxEvents()][e.numThreads()];
+ lastrd=new long[e.numEvents()+1][e.numObjects()];
+ lastwr=new long[e.numEvents()+1][e.numObjects()];
shorttesttime=time;
computeFinishing(time);
}
-
- int currbest;
- int shorttesttime;
+
+ long currbest;
+ long shorttesttime;
int[][] schedule;
int[] turn;
- int[][] lasttime;
- int[][] schedtime;
- int[][] lastrd;
- int[][] lastwr;
+ long[][] lasttime;
+ long[][] schedtime;
+ long[][] lastrd;
+ long[][] lastwr;
- public int getTime() {
+ public long getTime() {
return currbest;
}
- private void computeFinishing(int totaltime) {
+ private void computeFinishing(long totaltime) {
for(int threadnum=0;threadnum<e.numThreads();threadnum++) {
ThreadClass thread=e.getThread(threadnum);
- int threadtime=totaltime;
+ long threadtime=totaltime;
for(int transnum=thread.numTransactions()-1;transnum>=0;transnum--) {
Transaction trans=thread.getTransaction(transnum);
- int ltime=trans.getTime(trans.numEvents()-1);
+ long ltime=trans.getTime(trans.numEvents()-1);
threadtime-=ltime;
lasttime[transnum][threadnum]=threadtime;
}
//compute start time
ThreadClass thread=e.getThread(iturn);
int transnum=schedule[0][iturn]-schedule[step][iturn];
- int starttime=0;
+ long starttime=0;
if (transnum>0) {
starttime=schedtime[transnum-1][iturn];
Transaction prevtrans=thread.getTransaction(transnum-1);
//Let's check for object conflicts that delay start time
Transaction trans=thread.getTransaction(transnum);
for(int ev=0;ev<trans.numEvents();ev++) {
- int evtime=trans.getTime(ev);
+ long evtime=trans.getTime(ev);
int evobject=trans.getObject(ev);
+
switch(trans.getEvent(ev)) {
case Transaction.READ:
{
//just need to check write time
- int newstart=lastwr[step][evobject]-evtime;
+ long newstart=lastwr[step][evobject]-evtime;
if (newstart>starttime)
starttime=newstart;
break;
case Transaction.WRITE:
{
//just need to check both write and read times
- int newstart=lastwr[step][evobject]-evtime;
+ long newstart=lastwr[step][evobject]-evtime;
if (newstart>starttime)
starttime=newstart;
lastwr[step+1][obj]=lastwr[step][obj];
}
- int finishtime=starttime+trans.getTime(trans.numEvents()-1);
+ long finishtime=starttime+trans.getTime(trans.numEvents()-1);
//Update read and write times
for(int ev=0;ev<trans.numEvents();ev++) {
- int evtime=trans.getTime(ev);
+ long evtime=trans.getTime(ev);
int evobject=trans.getObject(ev);
switch(trans.getEvent(ev)) {
case Transaction.READ: {
boolean lgood=scheduleTask(step, iturn);
if (step==lastEvent&&lgood) {
- int maxfinish=0;
+ long maxfinish=0;
for(int i=0;i<e.numThreads();i++) {
int numTrans=e.getThread(i).numTransactions();
- int startt=schedtime[numTrans-1][i];
+ long startt=schedtime[numTrans-1][i];
Transaction lasttrans=e.getThread(i).getTransaction(numTrans-1);
- int finisht=startt+lasttrans.getTime(lasttrans.numEvents()-1);
+ long finisht=startt+lasttrans.getTime(lasttrans.numEvents()-1);
if (finisht>maxfinish)
maxfinish=finisht;
}
this.out=out;
}
- public void addPoint(int x, int y) {
- addPoint(Integer.toString(x), Integer.toString(y));
+ public void addPoint(long x, int y) {
+ addPoint(Long.toString(x), Integer.toString(y));
+ }
+
+ public void addPoint(int x, long y) {
+ addPoint(Integer.toString(x), Long.toString(y));
}
public void addPoint(String time, String value) {
--- /dev/null
+public class TEvent {
+ public int type;
+ public int index;
+ public int oid;
+ public long time;
+
+ public TEvent(int type, long time) {
+ this.time=time;
+ this.type=type;
+ this.oid=-1;
+ this.index=-1;
+ }
+
+ public TEvent(int type, long time, int oid) {
+ this.time=time;
+ this.type=type;
+ this.oid=oid;
+ this.index=-1;
+ }
+
+ public TEvent(int type, long time, int oid, int index) {
+ this.time=time;
+ this.type=type;
+ this.oid=oid;
+ this.index=index;
+ }
+}
\ No newline at end of file
}
boolean stalled;
int oid;
+ int index;
public void setObject(int oid) {
this.oid=oid;
}
+ public void setIndex(int index) {
+ this.index=index;
+ }
+
public int getObject() {
return oid;
}
+ public int getIndex() {
+ return index;
+ }
+
+ public void setObjIndex(ObjIndex oi) {
+ oid=oi.object;
+ index=oi.index;
+ }
+
+ public ObjIndex getObjIndex() {
+ return new ObjIndex(oid, index);
+ }
+
public boolean isStalled() {
return stalled;
}
public class TransSim {
public static void main(String[] args) {
- int numThreads=8;
+ int numThreads=20;
int numTrans=4;
int deltaTrans=0;
int numObjects=200;
Plot p=new Plot("plot");
- for(int i=1;i<40;i+=1) {
+ for(int i=10;i<800;i+=5) {
System.out.println("i="+i);
- Executor e=new Executor(numThreads, numTrans, deltaTrans, numObjects, i, deltaAccesses, readPercent, delay, deltaDelay, nonTrans, deltaNonTrans, splitobjects, splitaccesses, readPercentSecond);
+ Executor e=new Executor(numThreads, numTrans, deltaTrans, i, numAccesses, deltaAccesses, readPercent, delay, deltaDelay, nonTrans, deltaNonTrans, splitobjects, splitaccesses, readPercentSecond);
System.out.println(e.maxTime());
FlexScheduler ls=new FlexScheduler(e, FlexScheduler.LAZY, null);
ls.dosim();
public class Transaction {
int[] events;
int[] objects;
- int[] times;
+ int[] indices;
+ long[] times;
public String toString() {
String s="";
public static final int READ=0;
public static final int WRITE=1;
+ public static final int BARRIER=2;
public static final int DELAY=-1;
+ public static Transaction getBarrier() {
+ Transaction t=new Transaction(1);
+ t.setEvent(0, BARRIER);
+ return t;
+ }
+
public Transaction(int size) {
events=new int[size];
objects=new int[size];
- times=new int[size];
+ indices=new int[size];
+ times=new long[size];
}
public int numEvents() {
return events[index];
}
- public int getTime(int index) {
+ public long getTime(int index) {
return times[index];
}
return objects[index];
}
+ public int getIndex(int index) {
+ return indices[index];
+ }
+
+ public ObjIndex getObjIndex(int index) {
+ int obj=objects[index];
+ if (obj==-1)
+ return null;
+ return new ObjIndex(obj, indices[index]);
+ }
+
public void setEvent(int index, int val) {
events[index]=val;
}
- public void setTime(int index, int val) {
+ public void setTime(int index, long val) {
times[index]=val;
}
public void setObject(int index, int val) {
objects[index]=val;
}
+
+ public void setIndex(int index, int val) {
+ indices[index]=val;
+ }
}
\ No newline at end of file