From: <lan...@us...> - 2003-08-03 21:01:51
|
Update of /cvsroot/webmacro/webmacro/src-optional/org/opendoors/util In directory sc8-pr-cvs1:/tmp/cvs-serv16489/src-optional/org/opendoors/util Added Files: PostponeObservable.java Timer.java Log Message: doc improvements; moved sources to src-optional; implemented build policy: build with webmacro.defaults.classic but with a property switch be able to build with webmacro.defaults.minimal --- NEW FILE: PostponeObservable.java --- /* * Copyright Open Doors Software and Acctiva, 1996-2001. * All rights reserved. * * Software is provided according to the MPL license. * Open Doors Software and Acctiva provide this * software on an as-is basis and make no representation as * to fitness for a specific purpose. * * Direct all questions and comments to su...@op... */ package org.opendoors.util; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.Observable; import java.util.Observer; /** * PostponeObservable is the delegated instance for an observable * with the following characteristic: notification of the change arrives * after the observable has not changed for a period of n milliseconds. * <p> * This pattern solves a fundamental problem, namely thrashing. Thrashing * occurs when the same action occurs repeatedly over short periods of * time because the same event is fired, usually hundreds or thousand of * times per second. * <p> * So, for example, if a cache changes thousands of times per second during * a load or a transition to a new working set, how many times do you want * to refresh it? Once or a thousand times? An instance of PostponeObservable * allows your cache (or any changing object) to notify that it has changed * just once. * <p> * Thus, changes are deferred so that the observers * of the changes are not inundated with notifications. * <p> * Since this class implements the PropertyChangeListener interface, the class * PropertyChangeSupport may also be employed as well to notify * observers of changes. * <p> * This class is extends java.util.Observable. Observers must implement the * interface java.util.Observer. * <p><b>Note:</b> Shared instances of a PostponeObservable must implement their * own synchronizing strategy. * <p>Postponeability may be enabled/disabled at runtime. * @see java.util.Observable * @see java.util.Observer */ public class PostponeObservable extends Observable implements PropertyChangeListener { //-------public members----- /** * On property change, postpone event notification this number of millis. */ protected int postponeInterval = 120000; //2 minutes /** * While waiting to fire a notification, * reset the interval if another change comes in. */ protected boolean resetClockOnUpdate = true; //-------private and protected members----- private long timeToNotify = System.currentTimeMillis(); private Timer tick = null; //-------constructor(s)----- /** * Constructs a default observable. */ public PostponeObservable () { init(); } /** * Constructs a default observable with the following settings. * @param The interval to wait in millis between notifications. * @param Resets the clock so that changes can be aggregated * over a period of time */ public PostponeObservable (int postponeInterval, boolean resetClockOnUpdate) { this.postponeInterval = postponeInterval; this.resetClockOnUpdate = resetClockOnUpdate; init(); } /** Initializes the instance. */ protected void init () { tick = new Timer("PropertyObservable", postponeInterval, false); tick.addObserver(new TimerObserver()); } //-------public initializers/destroyers----- /** Sets the observable period. */ public void setPostponePeriod (int postponeInterval) { this.postponeInterval = postponeInterval; tick.setPeriod(postponeInterval); } /** Enables postponeability if true. */ public void enablePostponeability (boolean enable) { this.resetClockOnUpdate = enable; } //-------public event handlers----- /** * Using the property event model * propagate a change event to the observable. * @param evt The property change event which can be null. */ public void propertyChange (PropertyChangeEvent evt) { setChanged(); } /** * Call back from the timer when * the observation period has expired. */ public void timerAction () { if (hasChanged() && (timeToNotify < System.currentTimeMillis())) { notifyObservers(); } } /** * Signals that the observable has changed. * <p> * Observers will be * notified when * <pre> * current time > (time of last change + postponeInterval) * </pre> * provided postponeability is enabled. */ public void setChanged () { super.setChanged(); if (resetClockOnUpdate) { timeToNotify = (System.currentTimeMillis() + postponeInterval); } } /** Destoys this instance and the associated timer. */ public void destroy () { tick.stop(); tick = null; } /** * Class which listens to updates in the observable tick and calls * the timer notifiction method. */ class TimerObserver implements Observer { public void update (Observable o, Object arg) { timerAction(); } } } --- NEW FILE: Timer.java --- /* * Copyright Open Doors Software and Acctiva, 1996-2001. * All rights reserved. * * Software is provided according to the MPL license. * Open Doors Software and Acctiva provide this * software on an as-is basis and make no representation as * to fitness for a specific purpose. * * Direct all questions and comments to su...@op... */ package org.opendoors.util; import java.io.Serializable; import java.util.Observable; /** * This class provides timer and supporting events to client objects * by extending the Observable base class. Clients get notifications * of changes in the clock. * <p> * The interval for firing changes to observers is resetable in the event * the observer needs more frequent updates of changes. * <p> * The instance may be a one shot timer as well as a recurring timers. This * supports a one shot notification in the future. * <p> * Observable is thread-safe and supports multiple listeners to a single * observable such as an observable which fires every 24 hours. */ public class Timer extends Observable implements Runnable, Serializable { /** The timer thread. */ private transient Thread timerThread; /** Signal to stop the thread. */ private transient boolean stopThread = false; /** The name. */ private String name; /** The interval for firing. */ private int period; // in milliseconds /** Is a one shot timer. */ private boolean oneShot; /** * Public constructor to create a timer event source using factory defaults * which are 1 second timer, recurring. */ public Timer () { this("PerSecondTimer", 1000, false); } /** * Construct a timer with the certain properties set. * @param The name of the timer. * @param The period in milliseconds. * @param True if this is a oneShot instance */ public Timer (String name, int period, boolean oneShot) { super(); // Set properties this.name = name; this.period = period; this.oneShot = oneShot; // Create the clock thread timerThread = new Thread(this, name); timerThread.setDaemon(true); timerThread.start(); } /** * Stop the timer */ public void stop () { stopThread = true; } // Accessor methods /** * Gets the name of the timer. * @return The timer name. */ public String getName () { return name; } /** * Sets the name of the timer. * @param The textual name. */ public void setName (String n) { name = n; } /** * Gets the period between timer events. * @return The interval in milliseconds */ public int getPeriod () { return period; } /** * Sets the period in milliseconds. * @param The interval. */ public void setPeriod (int p) { period = p; if (timerThread != null) timerThread.interrupt(); } /** * Interrogates if this is a one-shot operation. * @return True, if a one-shot operation. */ public boolean isOneShot () { return oneShot; } /** * Set this object to be one-shot or not. * @param True, if one-shot operation desired */ public void setOneShot (boolean os) { oneShot = os; } /** * Run the timer. */ public void run () { while (timerThread != null) { // Sleep for the period try { timerThread.sleep(period); } catch (InterruptedException e) { // Restart the loop continue; } // Fire an action event setChanged(); notifyObservers(); if (oneShot || stopThread) break; } // clean up: timerThread = null; } } |