Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Monitor.java

00001 package gov.nasa.arc.ase.jpf.jvm;
00002 
00003 import gov.nasa.arc.ase.util.Debug;
00004 import gov.nasa.arc.ase.util.HashData;
00005 import gov.nasa.arc.ase.jpf.InternalErrorException;
00006 import java.io.*;
00007 //#ifdef JDK11
00008 
00009 
00010 //#else JDK11
00011 import java.util.*;
00012 //#endif JDK11
00013 //#ifdef RACE
00014 
00015 //#endif RACE
00016 
00017 /**
00018  * Represents the monitor associate with classes and objects.
00019  */
00020 public class Monitor { 
00021   /**
00022    * The identifier of the thread locking an object.
00023    */
00024   private int lockingThread;
00025 
00026   /**
00027    * The number of nested locks acquired.
00028    */
00029   private int lockCount;
00030 
00031   /**
00032    * The list of threads waiting to be notified.
00033    */
00034   private int[] waitingThreads;
00035 
00036   /**
00037    * Creates a new empty monitor.
00038    */
00039   public Monitor() {
00040     lockingThread = -1;
00041     lockCount = 0;
00042     waitingThreads = new int[0];
00043   }  
00044   /**
00045    * Returns true if it is possible to lock the monitor.
00046    */
00047   public boolean canLock(ThreadInfo th) {
00048     if (lockingThread == -1) return true;
00049 
00050     return (lockingThread == th.index);
00051   }  
00052   /**
00053    * Creates a clone of the monitor.
00054    */
00055   public Object clone() {
00056     Monitor m = new Monitor();
00057 
00058     m.lockingThread = lockingThread;
00059     m.lockCount = lockCount;
00060     m.waitingThreads = new int[waitingThreads.length];
00061     System.arraycopy(waitingThreads, 0, m.waitingThreads, 0, waitingThreads.length);
00062 
00063     return m; 
00064   }  
00065   /**
00066    * Compares to another object.
00067    */
00068   public boolean equals(Object o) {
00069     if(o == null) return false;
00070     if(!(o instanceof Monitor)) return false;
00071 
00072     Monitor m    = (Monitor)o;
00073 
00074     if (lockingThread != m.getLockingThread()) return false;
00075     if (lockCount != m.getLockCount()) return false;
00076 
00077     int[] w = m.waitingThreads;
00078 
00079     if (waitingThreads.length != w.length) return false;
00080 
00081     for(int i = 0; i < waitingThreads.length; i++)
00082       if(waitingThreads[i] != w[i]) return false;
00083 
00084     return true;
00085   }  
00086   /**
00087    * Returns the number of nested locks acquired.
00088    */
00089   public int getLockCount() {
00090     return lockCount;
00091   }  
00092   /**
00093    * Returns the identifier of the thread holding the lock.
00094    */
00095   public int getLockingThread() {
00096     return lockingThread;
00097   }  
00098   /**
00099    * Returns the list of waiting threads.
00100    */
00101   public int[] getWaitingThreads() {
00102     return waitingThreads;
00103   }  
00104   public void hash(HashData hd) {
00105     hd.add(lockingThread);
00106     hd.add(lockCount);
00107 
00108     for(int i = 0, l = waitingThreads.length; i < l; i++)
00109       hd.add(waitingThreads[i]);
00110   }  
00111   public int hashCode() {
00112     HashData hd = new HashData();
00113 
00114     hash(hd);
00115 
00116     return hd.getValue();
00117   }  
00118   /**
00119    * Interrupts one of the threads holding the lock.
00120    */
00121   public void interrupt(ThreadInfo th) {
00122     remove(th.index);
00123     th.setStatus(ThreadInfo.INTERRUPTED);
00124   }  
00125   /**
00126    * Acquires the lock for a given object or class.
00127    */
00128   public void lock(ThreadInfo th, Ref ref) {
00129     if(lockingThread == -1) {
00130       lockingThread = th.index;
00131 
00132 //#ifdef RACE || LOCK_ORDER
00133 
00134 //#endif LOCK_ORDER
00135     } else
00136       if(lockingThread != th.index)
00137     throw new InternalErrorException("lock operation failed");
00138     lockCount++;  
00139   }  
00140   /**
00141    * Tries to require the lock after being notified.
00142    */
00143   public void lockNotified(ThreadInfo th, Ref ref) {
00144     if (lockingThread != -1)
00145       throw new InternalErrorException("lock operation failed");
00146 
00147     lockingThread = th.index;
00148     lockCount = th.getLockCount();
00149     
00150     //** warning: should have been done when interrupted was set.   **//
00151     for(int i = 0; i < waitingThreads.length; i++)
00152       if(waitingThreads[i] == th.index) {
00153     remove(i);
00154     break;
00155       }
00156 
00157     th.setStatus(ThreadInfo.RUNNING);
00158     th.setLockCount(0);
00159   }  
00160   public void log() {
00161     Debug.println(Debug.MESSAGE, "    $lockingThread$: " + lockingThread);
00162     Debug.println(Debug.MESSAGE, "    $lockCount$: " + lockCount);
00163     Debug.print(Debug.MESSAGE, "    $waitingThreads$: { ");
00164     for(int i = 0, l = waitingThreads.length; i < l; i++) {
00165       if(i != 0) Debug.print(Debug.MESSAGE, ", ");
00166       Debug.print(Debug.MESSAGE, Integer.toString(waitingThreads[i]));
00167     }
00168     Debug.println(Debug.MESSAGE, " }");
00169   }  
00170   /**
00171    * Notifies one of the threads. The thread is chosen non deterministically.
00172    */
00173   public void notify(SystemState ss) {
00174     int length = waitingThreads.length;
00175 
00176     if(length == 0) return;
00177 
00178     int random = ss.random(length);
00179 
00180     ss.ks.tl.get(remove(random)).setStatus(ThreadInfo.NOTIFIED);
00181   }  
00182   /**
00183    * Notifies all waiting threads.
00184    */
00185   public void notifyAll(SystemState ss) {
00186     for(int i = 0, l = waitingThreads.length; i < l; i++) {
00187       ThreadInfo th = ss.ks.tl.get(waitingThreads[i]);
00188       th.setStatus(ThreadInfo.NOTIFIED);
00189     }
00190 
00191     waitingThreads = new int[0];
00192   }  
00193   private int remove(int index) {
00194     int r = waitingThreads[index];
00195     int length = waitingThreads.length;
00196 
00197     int[] n = new int[length - 1];
00198     System.arraycopy(waitingThreads, 0, n, 0, index);
00199     System.arraycopy(waitingThreads, index+1, n, index, length - index - 1);
00200     waitingThreads = n;
00201 
00202     return r;
00203   }  
00204   public String toString() {
00205     StringBuffer sb = new StringBuffer();
00206 
00207     sb.append("Monitor(");
00208     sb.append("lockingThread=");
00209     sb.append(lockingThread);
00210     sb.append(',');
00211     sb.append("lockCount=");
00212     sb.append(lockCount);
00213     sb.append(',');
00214     sb.append("waitingThreads=");
00215     sb.append('[');
00216     for(int i = 0; i < waitingThreads.length; i++) {
00217       if(i != 0)
00218     sb.append(',');
00219       sb.append(waitingThreads[i]);
00220     }
00221     sb.append(']');
00222     sb.append(')');
00223 
00224     return sb.toString();
00225   }  
00226   /**
00227    * Releases the lock. The lock can be still held by the thread
00228    * if it had been locked more than once.
00229    */
00230   public void unlock(ThreadInfo th, Ref ref) {
00231     lockCount--;
00232 
00233     if(lockCount < 0)
00234       throw new InternalErrorException("lock counter can't be negative");
00235 
00236     if (lockCount == 0) {
00237       lockingThread = -1;
00238 //#ifdef RACE || LOCK_ORDER
00239 
00240 //#endif RACE || LOCK_ORDER
00241     }
00242   }  
00243   /**
00244    * Waits to be notified. Releases the lock and waits.
00245    */
00246   public void wait(ThreadInfo th, Ref ref) {
00247     if(lockingThread != th.index)
00248       throw new InternalErrorException("wait on an unlocked monitor");
00249 
00250     th.setStatus(ThreadInfo.WAITING);
00251     th.setLockCount(lockCount);
00252 
00253     int length = waitingThreads.length;
00254     int[] n = new int[length + 1];
00255     System.arraycopy(waitingThreads, 0, n, 0, length);
00256     waitingThreads = n;
00257     waitingThreads[length] = th.index;
00258 
00259     lockingThread = -1;
00260     lockCount = 0;
00261 
00262 //#ifdef RACE || LOCK_ORDER
00263 
00264 //#endif RACE || LOCK_ORDER
00265   }  
00266 }

Generated at Thu Feb 7 06:50:31 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001