All computer source code presented on this page, unless it includes attribution to another author, is provided by Ed Halley under the Artistic License. Use such code freely and without any expectation of support. I would like to know if you make anything cool with the code, or need questions answered.
python/
    bindings.py
    boards.py
    buzz.py
    caches.py
    cards.py
    constraints.py
    csql.py
    english.py
    getch.py
    getopts.py
    gizmos.py
    goals.py
    improv.py
    interpolations.py
    namespaces.py
    nihongo.py
    nodes.py
    octalplus.py
    patterns.py
    physics.py
    pids.py
    pieces.py
    quizzes.py
    recipes.py
    relays.py
    romaji.py
    ropen.py
    sheets.py
    stores.py
    strokes.py
    subscriptions.py
    svgbuild.py
    testing.py
    things.py
    timing.py
    ucsv.py
    useful.py
    uuid.py
    vectors.py
    weighted.py
java/
    CSVReader.java
    CSVWriter.java
    GlobFilenameFilter.java
    RegexFilenameFilter.java
    StringBufferOutputStream.java
    ThreadSet.java
    Throttle.java
    TracingThread.java
    Utf8ConsoleTest.java
    droid/
        ArrangeViewsTouchListener.java
        DownloadFileTask.java
perl/
    CVQM.pm
    Kana.pm
    Typo.pm
cxx/
    CCache.h
    equalish.cpp
Download Throttle.java
/* $(#)Throttle.java : The cc.halley.kata.util.Throttle class.
**
**********
**
** Copyright (C) 1991-2001 Ed Halley
** http://www.halley.cc/ed/
**
** This file belongs to a package that is released according to the General
** Artistic License.  In essence, all files of the package are a part of a
** standard version which is held by standard copyright law, and fixes or
** additions must be in the public domain or given to the copyright holder
** for future standard versions.  See the file LICENSE.txt for details about
** the General Artistic License.
**
**********
**
** Created: Ed Halley / edh / ed@halley.cc
**
**********
*/

package cc.halley.kata.util;

import java.io.*;
import java.util.*;

/**
 * A <tt>Throttle</tt> is an abstract controller of behavior, limiting
 * how often an application-defined event may pass through to cause a
 * reaction.  It is conceptually like a faucet, able to limit the flow of
 * observable events or even turn the flow on or off completely.
 *
 * <p>At least two concrete extensions of <tt>Throttle</tt> are offered.
 * The <tt>CountThrottle</tt> counts occurrences, so that every fifth
 * event (for example) passes through the throttle.  The
 * <tt>DateThrottle</tt> watches the clock and calendar, so that only one
 * event passes through the throttle in any given hour (for example).
 * Other extensions are possible.
 *
 * @see CountThrottle
 * @see DateThrottle
 *
 * @author <a href="mailto:ed@halley.cc">Ed Halley</a>
 */

public abstract class Throttle
        implements Serializable
{
        /**
         * Create a new <tt>Throttle</tt>.
         */
        public Throttle()
                { ; }

        /**
         * Create a new <tt>Throttle</tt> with a specified flow.
         */
        public Throttle(long flow)
                { setFlowControl(flow); }

        /////////////////////////////////////////////////////////////////////

        /** The flow control. */
        protected long flow = 0;

        /**
         * Retrieve the current flow control of the throttle.  A throttle
         * only allows an event to <tt>pass()</tt> if the current stamp has
         * increased by at least this much since the last successful passage.
         *
         * @return The flow control for the throttle.
         */
        public long getFlowControl()
                { return flow; }

        /**
         * Adjust the current flow control of the throttle.  A throttle only
         * allows a true <tt>passEvent()</tt> if the current stamp has
         * increased by at least this much since the last successful passage.
         *
         * <p>Unless otherwise redefined by an extended class, a negative
         * flow will turn off the throttle's flow completely, and a flow
         * control of zero allows all events to pass through the throttle.
         *
         * @param flow The amount of flow to require between event passages.
         */
        public void setFlowControl(long flow)
                { this.flow = flow; }

        /////////////////////////////////////////////////////////////////////

        /** The current stamp at the time of the last successful pass. */
        protected long lastpass = 0;

        /**
         * Get the measurement of potential "current."
         *
         * <p>This is abstract and must be defined by a subclass.  In a
         * counting throttle, for example, the stamp would be a simple
         * integer that is increased each time the <tt>passEvent()</tt>
         * method is called.  In a clocktime-oriented throttle, the stamp
         * would be the actual time.
         *
         * <p>In any type of throttle, the stamp should either hold steady or
         * naturally increase in value with each call; it should not regress
         * in value negatively except by overflow.  The throttle detects
         * regression as a numeric overflow, and compensates.
         *
         * @return An extension should return the stamp as a long integer.
         */
        public abstract long getCurrentStamp();

        /**
         * Inspect the application-defined event object to reject or tally.
         *
         * <p>The actual event is completely ignored in the default
         * implementation of this method (and can be <tt>null</tt>).  All
         * events are compatible with passage; it is solely up to the flow
         * control to determine whether the event will pass or not.
         *
         * <p>An extended class may decide to completely ignore some kinds of
         * events, or to monitor the attempts of passage, by overriding this
         * method.
         *
         * @param event An application-defined object representing the event.
         * @return True, since all events are compatible by default.
         */
        protected boolean filterEvent(Object event)
                { return true; }

        /**
         * Note the flow of an application-defined event.
         *
         * <p>The actual event is completely ignored in the default
         * implementation of this method (and can be <tt>null</tt>).
         *
         * <p>An extended class may want to tally or track those events which
         * were allowed to pass through the <tt>passEvent()</tt> method, by
         * overriding this method.
         *
         * @param event An application-defined object representing the event.
         * @return True, since all events are compatible by default.
         */
        protected void allowEvent(Object event)
                { ; }

        /**
         * Request passage for a given application-defined event.  The
         * throttle takes this opportunity to compare the current stamp
         * against the last known successful passage.
         *
         * <p>The default behavior is usually sufficient for most types of
         * throttles.  The event is offered to the <tt>filterEvent()</tt>
         * method, which may tally all attempted events or filter
         * incompatible events out of the flow.  If the event will be allowed
         * through the throttle, it is also offered to the
         * <tt>allowEvent()</tt> method for any tracking required there.
         *
         * <p>The throttle detects numeric overflow of the values returned by
         * <tt>getCurrentStamp()</tt>, and compensates.
         *
         * @param event An application-defined object representing the event.
         * @return True if the event should be passed, or false if the
         *         throttle declines to pass the event.
         */
        public boolean passEvent(Object event)
        {
                if (flow < 0)
                        return false;
                if (!filterEvent(event))
                        return false;
                long stamp = getCurrentStamp();
                long overflow = 0;
                if (stamp < lastpass)
                        overflow = (Long.MAX_VALUE - lastpass) + 1;
                if ((stamp+overflow) < ((lastpass+overflow) + flow))
                        return false;
                allowEvent(event);
                lastpass = stamp;
                return true;
        }

}


Contact Ed Halley by email at ed@halley.cc.
Text, code, layout and artwork are Copyright © 1996-2013 Ed Halley.
Copying in whole or in part, with author attribution, is expressly allowed.
Any references to trademarks are illustrative and are controlled by their respective owners.
Make donations with PayPal - it's fast, free and secure!