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

BSLObserver.java

00001 // Environment consists of 
00002 //  - a thread that non-deterministically adds and deletes observers 
00003 //    for an observable
00004 //  - a thread that repeatedly changes the observables state
00005 //
00006 // This environment can be scaled to vary the number of observers, NUM_O, and
00007 // observables, NUM_S.
00008 //
00009 import edu.ksu.cis.bandera.abstraction.Abstraction;
00010 
00011 public class BSLObserver {
00012     public static void main(String[] args) {
00013                 Subject s = new Subject();
00014         new SubjectThread(s).start();
00015 
00016         Watcher w1 = new Watcher();
00017         Watcher w2 = new Watcher();
00018                
00019                 Watcher w;
00020         while (true) {
00021                   if (edu.ksu.cis.bandera.abstraction.Abstraction.choose()) {
00022             w = w1;
00023                   } else {
00024             w = w2;
00025                   }
00026           s.addObserver(w);
00027           s.deleteObserver(w);
00028                 }
00029 
00030     }
00031 }
00032 
00033 class SubjectThread extends Thread {
00034     Subject s;
00035     public SubjectThread(Subject s) {
00036         this.s = s;
00037     }
00038     public void run() {
00039           while (true) s.changeState();
00040     }
00041 }
00042 
00043 //class Subject extends Observable {
00044 class Subject {
00045     public void changeState() {
00046         setChanged();
00047         notifyObservers();
00048     }
00049 
00050 // copied from Observable
00051     protected boolean changed = false;
00052     protected Vector obs;
00053     public Subject() {
00054         obs = new Vector();
00055     }
00056 
00057         /**
00058           * @observable 
00059           *   RETURN end (this, Watcher watcher): watcher == o;
00060           */              
00061     public synchronized void addObserver(Watcher o) {
00062         if (!obs.contains(o)) {
00063             obs.addElement(o);
00064         }
00065     }
00066     protected synchronized void clearChanged() {
00067         changed = false;
00068     }
00069     public synchronized int countObservers() {
00070         return obs.size();
00071     }
00072         /**
00073           * @observable
00074           *   INVOKE begin (this, Watcher watcher): watcher == o;
00075           */              
00076     public synchronized void deleteObserver(Watcher o) {
00077         obs.removeElement(o);
00078     }
00079     public synchronized void deleteObservers() {
00080         obs.removeAllElements();
00081     }
00082     public synchronized boolean hasChanged() {
00083         return changed;
00084     }
00085     public void notifyObservers() {
00086         notifyObservers(null);
00087     }
00088 
00089             /* COMMENT FROM java.util.Observer
00090              *
00091              * We don't want the Observer doing callbacks  
00092              * into arbitrary code while holding its own Monitor.
00093              * The code where we extract each Observable from
00094              * the Vector and store the state of the Observer
00095              * needs synchronization, but notifying observers
00096              * does not (should not).  The worst result of any
00097              * potential race-condition here is that:
00098              * 1) a newly-added Observer will miss a
00099              *   notification in progress
00100              * 2) a recently unregistered Observer will be
00101              *   wrongly notified when it doesn't care
00102              */
00103 
00104         /**
00105           * @observable
00106           *   INVOKE begin (this);
00107           *   RETURN end (this);
00108           * @assert
00109           *   LOCATION[point] inWindow : false;
00110           */              
00111           //   LOCATION[point] inWindow (this, Watcher w): w == cw;
00112     public void notifyObservers(Object arg) {
00113                 Watcher cw;
00114         Object[] arrLocal;
00115         synchronized (this) {
00116             if (!changed)
00117                 return;
00118             arrLocal = obs.toArray();
00119             changed = false;
00120         }
00121         if (obs.size() != arrLocal.length) {
00122 point:            cw = null;
00123                 }
00124         for (int i = arrLocal.length - 1; i >= 0; i--) {
00125            cw = (Watcher) arrLocal[i];
00126            ((Watcher) arrLocal[i]).update(this, arg);
00127                 }  
00128     }
00129     protected synchronized void setChanged() {
00130         changed = true;
00131         }
00132 }
00133 
00134 //class Watcher implements Observer {
00135 class Watcher {
00136         /**
00137           * @observable 
00138           *   INVOKE begin (this, Subject subject): subject == o;
00139           */              
00140     public void update(Subject o, Object arg) { }
00141 }
00142 
00143 interface Observer {
00144         /**
00145           * @observable
00146           *   INVOKE begin (this, Observable subject): subject == o;
00147           */              
00148     public void update(Observable o, Object arg);
00149 }
00150 
00151 class Observable {
00152     protected boolean changed = false;
00153     protected Vector obs;
00154     public Observable() {
00155         obs = new Vector();
00156     }
00157 
00158         /**
00159           * @observable 
00160           *   RETURN end (this, Observer watcher): watcher == o;
00161           */              
00162     public synchronized void addObserver(Observer o) {
00163         if (!obs.contains(o)) {
00164             obs.addElement(o);
00165         }
00166     }
00167     protected synchronized void clearChanged() {
00168         changed = false;
00169     }
00170     public synchronized int countObservers() {
00171         return obs.size();
00172     }
00173         /**
00174           * @observable
00175           *   INVOKE begin (this, Observer watcher): watcher == o;
00176           */              
00177     public synchronized void deleteObserver(Observer o) {
00178         obs.removeElement(o);
00179     }
00180     public synchronized void deleteObservers() {
00181         obs.removeAllElements();
00182     }
00183     public synchronized boolean hasChanged() {
00184         return changed;
00185     }
00186     public void notifyObservers() {
00187         notifyObservers(null);
00188     }
00189 
00190             /* COMMENT FROM java.util.Observer
00191              *
00192              * We don't want the Observer doing callbacks  
00193              * into arbitrary code while holding its own Monitor.
00194              * The code where we extract each Observable from
00195              * the Vector and store the state of the Observer
00196              * needs synchronization, but notifying observers
00197              * does not (should not).  The worst result of any
00198              * potential race-condition here is that:
00199              * 1) a newly-added Observer will miss a
00200              *   notification in progress
00201              * 2) a recently unregistered Observer will be
00202              *   wrongly notified when it doesn't care
00203              */
00204 
00205         /**
00206           * @observable
00207           *   INVOKE begin (this);
00208           *   RETURN end (this);
00209           */              
00210     public void notifyObservers(Object arg) {
00211         Object[] arrLocal;
00212         synchronized (this) {
00213             if (!changed)
00214                 return;
00215             arrLocal = obs.toArray();
00216             changed = false;
00217         }
00218         for (int i = arrLocal.length - 1; i >= 0; i--)
00219              ((Observer) arrLocal[i]).update(this, arg);
00220     }
00221     protected synchronized void setChanged() {
00222         changed = true;
00223     }
00224 }
00225 
00226 class Vector {
00227     Object elementData[];
00228     int elementCount;
00229     public Vector() {
00230         this(3);
00231     }
00232     public Vector(int n) {
00233         elementData = new Object[n];
00234         elementCount = 0;
00235     }
00236     public boolean contains(Object elem) {
00237         return indexOf(elem, 0) >= 0;
00238     }
00239     public int indexOf(Object elem) {
00240         return indexOf(elem, 0);
00241     }
00242     public synchronized int indexOf(Object elem, int index) {
00243         if (elem == null) {
00244             for (int i = index; i < elementCount; i++)
00245                 if (elementData[i] == null)
00246                     return i;
00247         } else {
00248             for (int i = index; i < elementCount; i++)
00249                 if (elem == elementData[i])
00250                     return i;
00251         }
00252         return -1;
00253     }
00254     public synchronized void addElement(Object obj) {
00255         elementData[elementCount++] = obj;
00256     }
00257     public int size() {
00258         return elementCount;
00259     }
00260     public synchronized boolean removeElement(Object obj) {
00261         int i = indexOf(obj);
00262         if (i >= 0) {
00263             removeElementAt(i);
00264             return true;
00265         }
00266         return false;
00267     }
00268     private void arraycopy(Object[] src, int src_position, Object[] dest, int dest_position, int length) {
00269         for (int i = 0; i < length; i++) {
00270             dest[dest_position + i] = src[src_position + i];
00271         }
00272     }
00273     public synchronized void removeElementAt(int index) {
00274         if (index >= elementCount) {
00275             throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
00276         } else
00277             if (index < 0) {
00278                 throw new ArrayIndexOutOfBoundsException(index);
00279             }
00280         int j = elementCount - index - 1;
00281         if (j > 0) {
00282             arraycopy(elementData, index + 1, elementData, index, j);
00283         }
00284         elementCount--;
00285         elementData[elementCount] = null;
00286     }
00287     public synchronized void removeAllElements() {
00288         for (int i = 0; i < elementCount; i++)
00289             elementData[i] = null;
00290         elementCount = 0;
00291     }
00292     public synchronized Object[] toArray() {
00293         Object[] result = new Object[elementCount];
00294         arraycopy(elementData, 0, result, 0, elementCount);
00295         return result;
00296     }
00297 }

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