KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > util > SoftReferenceCache


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.util;
19
20 import java.lang.ref.SoftReference JavaDoc;
21 import java.util.HashMap JavaDoc;
22
23 /**
24  * This class manages a cache of soft references to objects that may
25  * take some time to load or create, such as images loaded from the
26  * network.
27  *
28  * Adding an object is two fold: <br />
29  * + First you add the key, this lets the cache know that someone is
30  * working on that key. <br />
31  * + Then when the completed object is ready you put it into the cache.<P>
32  *
33  * If someone requests a key after it has been added but before it has
34  * been put they will be blocked until the put.
35  */

36
37 public class SoftReferenceCache {
38     HashMap JavaDoc map = new HashMap JavaDoc();
39
40     /**
41      * Let people create there own caches.
42      */

43     protected SoftReferenceCache() { }
44
45
46     /**
47      * Let people flush the cache (remove any cached data). Pending
48      * requests will be treated as though clear() was called on the
49      * key, this should cause them to go and re-read the data.
50      */

51     public synchronized void flush() {
52         map.clear();
53         this.notifyAll();
54     }
55
56     /**
57      * Check if <tt>request(key)</tt> will return with an Object
58      * (not putting you on the hook for it). Note that it is possible
59      * that this will return true but between this call and the call
60      * to request the soft-reference will be cleared. So it
61      * is still possible for request to return NULL, just much less
62      * likely (you can always call 'clear' in that case).
63      */

64     protected final synchronized boolean isPresentImpl(Object JavaDoc key) {
65         if (!map.containsKey(key))
66             return false;
67
68         Object JavaDoc o = map.get(key);
69         if (o == null)
70             // It's been requested but hasn't been 'put' yet.
71
return true;
72
73         // It's been put let's make sure the soft reference hasn't
74
// been cleared.
75
SoftReference JavaDoc sr = (SoftReference JavaDoc)o;
76         o = sr.get();
77         if (o != null)
78             return true;
79
80         // Soft reference was cleared, so remove our record of key.
81
clearImpl(key);
82         return false;
83     }
84
85     /**
86      * Check if <tt>request(key)</tt> will return immediately with the
87      * Object. Note that it is possible that this will return
88      * true but between this call and the call to request the
89      * soft-reference will be cleared.
90      */

91     protected final synchronized boolean isDoneImpl(Object JavaDoc key) {
92         Object JavaDoc o = map.get(key);
93         if (o == null) return false;
94         SoftReference JavaDoc sr = (SoftReference JavaDoc)o;
95         o = sr.get();
96         if (o != null)
97             return true;
98
99         // Soft reference was cleared
100
clearImpl(key);
101         return false;
102     }
103
104     /**
105      * If this returns null then you are now 'on the hook'.
106      * to put the Object associated with key into the
107      * cache. */

108     protected final synchronized Object JavaDoc requestImpl(Object JavaDoc key) {
109         if (map.containsKey(key)) {
110
111             Object JavaDoc o = map.get(key);
112             while(o == null) {
113                 try {
114                     // When something is cleared or put we will be notified.
115
wait();
116                 }
117                 catch (InterruptedException JavaDoc ie) { }
118
119                 // check if key was cleared, if so it will most likely
120
// never be 'put'.
121
if (!map.containsKey(key))
122                     break;
123
124                 // Let's see if it was put...
125
o = map.get(key);
126             }
127             if (o != null) {
128                 SoftReference JavaDoc sr = (SoftReference JavaDoc)o;
129                 o = sr.get();
130                 if (o != null)
131                     return o;
132             }
133         }
134
135         // So now the caller get's the hot potato.
136
map.put(key, null);
137         return null;
138     }
139
140     /**
141      * Clear the entry for key.
142      * This is the easiest way to 'get off the hook'.
143      * if you didn't indend to get on it.
144      */

145     protected final synchronized void clearImpl(Object JavaDoc key) {
146         map.remove(key);
147         this.notifyAll();
148     }
149
150     /**
151      * Associate object with key. 'object' is only referenced through
152      * a soft reference so don't rely on the cache to keep it
153      * around. If the map no longer contains our url it was
154      * probably cleared or flushed since we were put on the hook
155      * for it, so in that case we will do nothing.
156      */

157     protected final synchronized void putImpl(Object JavaDoc key, Object JavaDoc object) {
158         if (map.containsKey(key)) {
159             SoftReference JavaDoc ref = new SoftRefKey(object, key);
160             map.put(key, ref);
161             this.notifyAll();
162         }
163     }
164
165     class SoftRefKey extends CleanerThread.SoftReferenceCleared {
166         Object JavaDoc key;
167         public SoftRefKey(Object JavaDoc o, Object JavaDoc key) {
168             super(o);
169             this.key = key;
170         }
171
172         public void cleared() {
173             SoftReferenceCache cache = SoftReferenceCache.this;
174             if (cache == null) return; // Can't really happen.
175
synchronized (cache) {
176                 Object JavaDoc o = cache.map.remove(key);
177                 if (this == o) {
178                     // Notify other threads that they may have
179
// to provide this resource now.
180
cache.notifyAll();
181                 } else {
182                     // Must not have been ours put it back...
183
// Can happen if a clear is done.
184
cache.map.put(key, o);
185                 }
186  
187             }
188         }
189     }
190 }
191
Popular Tags