001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.projectapi;
043:
044: // XXX COPIED from org.openide.util w/ changes:
045: // weak -> soft
046: // timeout
047: // removed map key functionality
048:
049: import java.lang.ref.WeakReference;
050: import org.openide.util.RequestProcessor;
051: import org.openide.util.Utilities;
052:
053: /**
054: * A weak reference which is held strongly for a while after last access.
055: * Lifecycle:
056: * <ol>
057: * <li>Created. Referent held strongly. A task is scheduled into the request
058: * processor for some time in the future (currently 15 seconds).</li>
059: * <li>Expired. After the timeout, the reference switches to a normal weak
060: * reference.</li>
061: * <li>Touched. If the value is accessed before it is garbage collected,
062: * whether the reference is expired or not, the reference is "touched".
063: * This means that the referent is again held strongly and the timeout
064: * is started from scratch.</li>
065: * <li>Dead. If after expiry there is no access before the next full GC cycle,
066: * the GC algorithm may reclaim the reference. In this case the reference
067: * of course dies.</li>
068: * </ol>
069: * @author Jesse Glick
070: */
071: public final class TimedWeakReference<T> extends WeakReference<T>
072: implements Runnable {
073:
074: public static int TIMEOUT = 15000;
075:
076: private static final RequestProcessor RP = new RequestProcessor(
077: "TimedWeakReference"); // NOI18N
078:
079: private RequestProcessor.Task task;
080:
081: private T o;
082:
083: /** Time when the object was last time touched */
084: private long touched;
085:
086: /**
087: * Create a weak reference with timeout.
088: * @param o the referent
089: */
090: public TimedWeakReference(T o) {
091: super (o, Utilities.activeReferenceQueue());
092: this .o = o;
093: task = RP.create(this );
094: task.schedule(TIMEOUT);
095: }
096:
097: public synchronized void run() {
098: if (o != null) {
099: //System.err.println("Expire " + k);
100: // how long we've really been idle
101: long unused = System.currentTimeMillis() - touched;
102: if (unused > TIMEOUT / 2) {
103: o = null;
104: touched = 0;
105: } else {
106: task.schedule(TIMEOUT - (int) unused);
107: }
108: }
109: }
110:
111: public synchronized T get() {
112: if (o == null) {
113: o = super .get();
114: }
115: if (o != null) {
116: // touch me
117: //System.err.println("Touch " + k);
118: if (touched == 0) {
119: task.schedule(TIMEOUT);
120: }
121: touched = System.currentTimeMillis();
122: return o;
123: } else {
124: return null;
125: }
126: }
127:
128: }
|