KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > TimedSoftReference


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.util;
20
21 import java.lang.ref.SoftReference JavaDoc;
22
23 import java.util.Map JavaDoc;
24
25
26 /**
27  * A soft reference which is held strongly for a while after last access.
28  * Lifecycle:
29  * <ol>
30  * <li>Created. Referent held strongly. A task is scheduled into the request
31  * processor for some time in the future (currently 30 seconds).</li>
32  * <li>Expired. After the timeout, the reference switches to a normal soft
33  * reference.</li>
34  * <li>Touched. If the value is accessed before it is garbage collected,
35  * whether the reference is expired or not, the reference is "touched".
36  * This means that the referent is again held strongly and the timeout
37  * is started from scratch.</li>
38  * <li>Dead. If after expiry there is no access before the next full GC cycle,
39  * the GC algorithm may reclaim the reference. In this case the reference
40  * of course dies. As a bonus, it will try to remove itself as the value
41  * from a map of your choice, to make it convenient to use these references
42  * as values in a caching map without leaking memory for the key.</li>
43  * </ol>
44  * @author Jesse Glick
45  */

46 final class TimedSoftReference<T> extends SoftReference JavaDoc<T> implements Runnable JavaDoc {
47     private static final int TIMEOUT = 30000;
48     private static final RequestProcessor RP = new RequestProcessor("TimedSoftReference"); // NOI18N
49
private RequestProcessor.Task task;
50     private T o;
51     private final Map JavaDoc m;
52     private final Object JavaDoc k;
53
54     /** Time when the object was last time touched */
55     private long touched;
56
57     /**
58      * Create a soft reference with timeout.
59      * The supplied map serves double duty as a synchronization lock
60      * for the reference's state changes.
61      * @param o the referent
62      * @param m a map in which this reference may serve as a value
63      * @param k the key whose value in <code>m</code> may be this reference
64      */

65     public TimedSoftReference(T o, Map JavaDoc m, Object JavaDoc k) {
66         super(o, Utilities.activeReferenceQueue());
67         this.o = o;
68         this.m = m;
69         this.k = k;
70         task = RP.create(this);
71         task.schedule(TIMEOUT);
72     }
73
74     public void run() {
75         synchronized (m) {
76             if (o != null) {
77                 //System.err.println("Expire " + k);
78
// how long we've really been idle
79
long unused = System.currentTimeMillis() - touched;
80
81                 if (unused > (TIMEOUT / 2)) {
82                     o = null;
83                     touched = 0;
84                 } else {
85                     task.schedule(TIMEOUT - (int) unused);
86                 }
87             } else {
88                 // clean up map ref, we are dead
89
//System.err.println("Die " + k);
90
m.remove(k);
91             }
92         }
93     }
94
95     public T get() {
96         synchronized (m) {
97             if (o == null) {
98                 o = super.get();
99             }
100
101             if (o != null) {
102                 // touch me
103
//System.err.println("Touch " + k);
104
if (touched == 0) {
105                     task.schedule(TIMEOUT);
106                 }
107
108                 touched = System.currentTimeMillis();
109
110                 return o;
111             } else {
112                 return null;
113             }
114         }
115     }
116 }
117
Popular Tags