/*
* ThreadedWRVectorModel.java, (c) Raimond Reichert July 1999
*/
package mldemo;
import java.util.*;
import java.lang.ref.*;
/**
* Implements VectorModel with weak references, ie, using
* a Vector to hold WeakReferences which in turn
* hold the references to the VectorModel.Listeners.
*
*
ThreadedWRVectorModel registers the
* WeakReferences with a ReferenceQueue. A
* dedicated threads waits for the reference objects to be enqueued. When that
* happens, this thead removes the reference objects from the queue, and
* also from the listeners vector.
*
* @author Raimond Reichert
*/
public class ThreadedWRVectorModel implements VectorModel {
private Vector vector;
private Vector listeners;
private ReferenceQueue queue;
private Thread cleanUpThread;
public ThreadedWRVectorModel() {
vector = new Vector();
listeners = new Vector();
queue = new ReferenceQueue();
Runnable cleanUp = new Runnable() {
public void run() {
Thread thisThread = Thread.currentThread();
WeakReference wr;
while (thisThread == cleanUpThread) {
try {
wr = (WeakReference)queue.remove();
System.out.println (
"ThreadedWRVectorModel: thread is removing weak reference"
);
listeners.removeElement (wr);
wr = null;
}
catch (InterruptedException e) { }
}
}
};
cleanUpThread = new Thread (cleanUp);
cleanUpThread.start();
} // ThreadedWRVectorModel //
public void addElement (Object object) {
vector.addElement (object);
fireElementAdded (object);
} // addElement //
public void removeElement (Object object) {
vector.removeElement (object);
fireElementRemoved (object);
} // removeElement //
public Object elementAt (int index) {
return vector.elementAt (index);
} // elementAt //
public int size() {
return vector.size();
} // size //
public void addListener (VectorModel.Listener l) {
WeakReference wr = new WeakReference (l, queue);
listeners.addElement (wr);
} // addListener //
public void removeListener (VectorModel.Listener l) {
int size = listeners.size();
int i = 0;
while (i < size) {
WeakReference wr = (WeakReference)listeners.elementAt(i);
VectorModel.Listener vml = (VectorModel.Listener)wr.get();
if (vml == l) {
listeners.removeElement (wr);
size--;
}
else
i++;
}
} // removeListener //
protected void fireElementAdded (Object object) {
VectorModel.Event e = null;
int size = listeners.size();
int i = 0;
while (i < size) {
WeakReference wr = (WeakReference)listeners.elementAt(i);
VectorModel.Listener vml = (VectorModel.Listener)wr.get();
if (vml != null) {
if (e == null) // lazily create event
e = new VectorModel.Event (this, object);
vml.elementAdded (e);
i++;
}
}
} // fireElementAdded //
protected void fireElementRemoved (Object object) {
VectorModel.Event e = null;
int size = listeners.size();
int i = 0;
while (i < size) {
WeakReference wr = (WeakReference)listeners.elementAt(i);
VectorModel.Listener vml = (VectorModel.Listener)wr.get();
if (vml != null) {
if (e == null) // lazily create event
e = new VectorModel.Event (this, object);
vml.elementRemoved (e);
i++;
}
}
} // fireElementRemoved //
public void terminate() {
if (cleanUpThread != null) {
System.out.println ("ThreadedWRVectorModel: terminated");
Thread moribound = cleanUpThread;
cleanUpThread = null;
moribound.interrupt();
}
} // terminate //
protected void finalize() throws Throwable {
System.out.println ("ThreadedWRVectorModel: finalized");
super.finalize();
} // finalize //
} // ThreadedWRVectorModel //