/* ZZObs.java * * Copyright (c) 2000, Ted Nelson and Tuomas Lukka * * You may use and distribute under the terms of either the GNU Lesser * General Public License, either version 2 of the license or, * at your choice, any later version. Alternatively, you may use and * distribute under the terms of the XPL. * * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of * the licenses. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README * file for more details. * */ /* * Written by Tuomas Lukka, queuing and enable/disable by Rauli Ruohonen */ package org.gzigzag; import java.util.*; /** A class used to trigger ZZObses. */ public class ZZObsTrigger { String rcsid = "$Id: ZZObsTrigger.java,v 1.6.2.1 2001/04/08 16:13:59 ajk Exp $"; public static boolean dbg = false; private static void p(String s) { if(dbg) ZZLogger.log(s); } private static void pa(String s) { ZZLogger.log(s); } // XXX Store weak references, not hard ones! private static Vector allTrigs = new Vector(); private static Hashtable obsQueue = new Hashtable(); private static Hashtable obsDisabled = new Hashtable(); ZZObsTrigger() { allTrigs.addElement(this); } /** An object which keeps track of the observations of a single * ZZObs. */ class Gob { /** Linked list of Gobs, plus list of all objects that this * Gob observes. * This is a tricky part and this is also what makes us blazingly * fast. And difficult to explain. *
* First of all, there is a key for every object that this
* gob's obs has been addObs'ed for.
* The value depends on whether there are other gobs observing
* the same thing. If there are, then the hashtables form a linked
* list. If not, or if this is the last element of the linked
* list, the value in the Hashtable is this gob.
* That may seem odd until you realize that 1) hashtables can't
* store nulls, and 2) this is a pointer that is
* very likely to be in a register so fast to compare with
* the reference.
*/
Hashtable next = new Hashtable();
/** The backward links. Only necessary links are stored. */
Hashtable prev = new Hashtable();
ZZObs obs;
}
/** Key: ZZObs; Value: Gob. */
Hashtable gobs = new Hashtable();
/** Key: Object (trigger); Value: Gob. */
Hashtable trigs = new Hashtable();
/** Called when something is changed.
* This call removes instances of the ZZObses triggered from
* all existing ZZObsTrigger objects.
*/
public synchronized void chg(Object o) {
Gob g,pg=null;
Hashtable next=trigs;
while((g = (Gob)next.get(o)) !=null && g!=pg) {
pg=g;
if(!chg(g.obs)) next=g.next;
}
// XXX This shouldn't be necessary! (views should use triggers)
ZZUpdateManager.chg();
}
public static boolean chg(ZZObs obs) {
// XXX This shouldn't be necessary! (views should use triggers)
ZZUpdateManager.chg();
synchronized(obsQueue) {
if(obsDisabled.containsKey(obs)) return false;
obsQueue.put(obs,obs);
for(int i=0; i