All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.org.retep.util.reference.AbstractDelayedWeakReference Maven / Gradle / Ivy

There is a newer version: 10.6
Show newest version
/*
 * 

Copyright (c) 1998-2009, Peter T Mount
* All rights reserved.

* *

Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met:

* *
    *
  • Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer.
  • * *
  • Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution.
  • * *
  • Neither the name of the retep.org.uk nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission.
  • * *
* *

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/ package uk.org.retep.util.reference; import uk.org.retep.util.thread.DelayedRunnableAdaptor; import static uk.org.retep.util.reference.ReferenceFactory.*; /** * A weak reference which is held strongly for a set period after the last access * to it. Once that period has expired it will then be available to the Garbage * Collector for disposal. * * @param Type of the referenced object * @author peter * @Since 9.6 */ public abstract class AbstractDelayedWeakReference extends CleanableWeakReference { /** * The default timeout of 10 seconds */ public static final long DEFAULT_TIMEOUT = 10000L; /** * The timeout for this reference */ private long timeout; /** * Hard reference to the object */ private T o; /** * Time when the object was last touched */ private long touched; /** * Our timer which will handle the timeout */ private DelayedRunnableAdaptor task; /** * Create a weak reference with timeout. * @param o the referent */ public AbstractDelayedWeakReference( final T o ) { this( DEFAULT_TIMEOUT, o ); } public AbstractDelayedWeakReference( final long timeout, final T o ) { super( o ); this.timeout = timeout; this.o = o; touched = System.currentTimeMillis(); schedule( timeout ); } @Override public void cleanupReference() { if( o != null ) { final long unused = System.currentTimeMillis() - touched; if( unused > timeout / 2 ) { o = null; touched = 0; unschedule(); // NB: Dont place unscheduled insude unschedule due to locking unscheduled(); } else { schedule( timeout - (int) unused ); } } else { remove( super.get() ); } } /** * Called when we remove the hard reference * @param o Object to remove or null if no longer present */ protected abstract void remove( T o ); /** * {@inheritDoc } */ @Override public synchronized T get() { if( o == null ) { o = super.get(); } if( o != null ) { if( touched == 0 ) { schedule( timeout ); } touched = System.currentTimeMillis(); touched(); return o; } else { return null; } } /** * Called whenever the entry is touched */ protected void touched() { } /** * Return the value held by this reference. * * Unlike {@link #get()} which ensures that the object will remain in memory * for the required delay, this method attempts to allow the object to be * removed by the garbage collector at its earliest convenience * @return Value or null if it's already been removed */ public synchronized T getAndRelease() { // Remove from the schedule, remove the hard reference and set touched // to the epoch. This way we are giving the gc all the hints to remove // the object unschedule(); o = null; touched = 0L; return super.get(); } /** * Returns the hashCode of the managed Object * @return hashCode of the managed Object or 0 if null (i.e. removed from * memory by the Garbage Collector) */ public synchronized int getHashCode() { final T v = get(); return v == null ? 0 : v.hashCode(); } private final synchronized void schedule( final long delay ) { if( task == null ) { task = new DelayedRunnableAdaptor( delay ) { @Override public void run() { cleanupReference(); } }; } else { task.setDelay( delay ); } getDelayThreadPoolExecutor().execute( task ); } private final synchronized void unschedule() { if( task != null ) { getDelayThreadPoolExecutor().remove( task ); } } /** * Called whenever we are unscheduled */ protected void unscheduled() { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy