package com.perforce.api;
import java.util.*;
/*
* Copyright (c) 2001, Perforce Software, All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* This hashtable build to contain objects that will decay over time. The
* objects stored must implement the Cacheable interface.
*
* @author <a href="mailto:david@markley.cc">David Markley</a>
* @version $Date: 2001/12/04 $ $Revision: #2 $
* @see java.util.Hashtable
* @see Cacheable
*/
public final class HashDecay extends Hashtable implements Runnable {
/** The minimum delay allowed */
public final static long MIN_DELAY = 0;
private long delay = MIN_DELAY;
private Thread decay_thread;
private boolean runForever = true;
private static Vector started = new Vector();
static {
started = new Vector();
}
public HashDecay() {
super();
}
public HashDecay(long delay) {
this();
setDelay(delay);
}
/**
* Sets the delay, in milliseconds, before items in the hashtable are
* discarded.
*/
public void setDelay(long delay) {
this.delay = (MIN_DELAY > delay) ? MIN_DELAY : delay;
}
/**
* Returns the delay.
*/
public long getDelay() {
return delay;
}
public void run() {
while(runForever) {
try {
Thread.sleep(delay);
} catch(InterruptedException iex) {
}
decay();
}
}
private synchronized void decay() {
long now = (new Date()).getTime();
Enumeration en = keys();
Object key;
while(en.hasMoreElements()) {
key = en.nextElement();
if(delay >= (now - ((Cacheable) get(key)).getUpdateTime())) {
super.remove(key);
}
}
}
public Object put(Object key, Object value) {
if(!(value instanceof Cacheable))
return null;
return put(key, (Cacheable) value);
}
public Object put(Object key, Cacheable value) {
value.refreshUpdateTime();
super.remove(key);
Object obj = super.put(key, value);
return obj;
}
public void start() {
if(null != decay_thread)
return;
runForever = true;
decay_thread = new Thread(this);
decay_thread.start();
started.addElement(this);
}
public void stop() {
runForever = false;
if(null == decay_thread)
return;
try {
decay_thread.interrupt();
decay_thread.join(100);
} catch(InterruptedException ex) {
decay_thread.destroy();
} catch(SecurityException ex) {
decay_thread.destroy();
}
}
/**
* Stops running threads for all HashDecay instances.
*/
public static void stopAll() {
HashDecay hd;
Enumeration en = started.elements();
while(en.hasMoreElements()) {
hd = (HashDecay) en.nextElement();
hd.stop();
}
}
}