/* * 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 //