KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > common > util > AbstractTwoStageCache


1 package org.objectweb.celtix.common.util;
2
3 import java.lang.ref.SoftReference JavaDoc;
4 import java.util.Iterator JavaDoc;
5 import java.util.LinkedList JavaDoc;
6 import java.util.Queue JavaDoc;
7
8
9 /**
10  * This class pools objects, for efficiency accross a lightweight
11  * fixed-size primary cache and a variable-size secondary cache - the
12  * latter uses soft references to allow the polled object be GCed if
13  * necessary.
14  * <p>
15  * To use the cache, a subclass is defined which provides an implementation
16  * of the abstract get() method - this may be conveniently achieved via
17  * an anonymous subclass. The cache is then populated by calling the
18  * populate_cache() method - the reason a two-stage process is used is
19  * to avoid problems with the inner class create() method accessing outer
20  * class data members from the inner class ctor (before its reference to
21  * the outer class is initialized).
22  * <p>
23  *
24  * @author Eoghan Glynn
25  */

26 public abstract class AbstractTwoStageCache<E> {
27     private Object JavaDoc mutex;
28     private int preallocation;
29     private int primaryCacheSize;
30     private int secondaryCacheHighWaterMark;
31     
32     private Queue JavaDoc<E> primaryCache;
33     private Queue JavaDoc<SoftReference JavaDoc<E>> secondaryCache;
34
35     /**
36      * Constructor.
37      *
38      * @param pCacheSize primary cache size
39      * @param secondary_cache_max secondary cache high water mark
40      * @param preallocation the number of object to preallocation when the
41      * cache is created
42      */

43     public AbstractTwoStageCache(int pCacheSize, int highWaterMark, int prealloc) {
44         this(pCacheSize, highWaterMark, prealloc, null);
45     }
46
47
48     /**
49      * Constructor.
50      *
51      * @param pCacheSize primary cache size
52      * @param secondary_cache_max secondary cache high water mark
53      * @param preallocation the number of object to preallocation when the
54      * cache is created
55      * @param mutex object to use as a monitor
56      */

57     public AbstractTwoStageCache(int pCacheSize, int highWaterMark, int prealloc, Object JavaDoc mutexParam) {
58         this.primaryCacheSize = Math.min(pCacheSize, highWaterMark);
59         this.secondaryCacheHighWaterMark = highWaterMark - pCacheSize;
60         this.preallocation = prealloc > highWaterMark ? highWaterMark : prealloc;
61         this.mutex = mutexParam != null ? mutexParam : this;
62     }
63
64     public String JavaDoc toString() {
65         return "AbstractTwoStageCache";
66     }
67
68
69     /**
70      * Over-ride this method to create objects to populate the pool
71      *
72      * @return newly created object
73      */

74     protected abstract E create() throws Exception JavaDoc;
75
76
77     /**
78      * Populate the cache
79      */

80     public void populateCache() throws Exception JavaDoc {
81         // create cache
82
primaryCache = new LinkedList JavaDoc<E>();
83         secondaryCache = new LinkedList JavaDoc<SoftReference JavaDoc<E>>();
84
85         // preallocate objects into primary cache
86
int primaryCachePreallocation =
87             (preallocation > primaryCacheSize) ? primaryCacheSize : preallocation;
88         for (int i = 0; i < primaryCachePreallocation; i++) {
89             primaryCache.offer(create());
90         }
91         
92         // preallocate objects into secondary cache
93
int secondaryCachePreallocation = preallocation - primaryCachePreallocation;
94         for (int i = 0; i < secondaryCachePreallocation; i++) {
95             secondaryCache.offer(new SoftReference JavaDoc<E>(create()));
96         }
97     }
98
99
100     /**
101      * Return a cached or newly created object
102      *
103      * @return an object
104      */

105     public E get() throws Exception JavaDoc {
106         E ret = poll();
107
108         if (ret == null) {
109             ret = create();
110         }
111
112         return ret;
113     }
114
115
116     /**
117      * Return a cached object if one is available
118      *
119      * @return an object
120      */

121     public E poll() {
122         E ret = null;
123
124         synchronized (mutex) {
125             if (primaryCache != null) {
126                 ret = primaryCache.poll();
127                 if (ret == null) {
128                     SoftReference JavaDoc<E> sr = secondaryCache.poll();
129                     while (ret == null && sr != null) {
130                         if (sr != null) {
131                             ret = sr.get();
132                         }
133                         if (ret == null) {
134                             sr = secondaryCache.poll();
135                         }
136                     }
137                 }
138             }
139         }
140
141         return ret;
142     }
143
144
145     /**
146      * Recycle an old Object.
147      *
148      * @param oldObject the object to recycle
149      * @return true iff the object can be accomodated in the cache
150      */

151     public boolean recycle(E oldObject) {
152         boolean cached = false;
153
154         synchronized (mutex) {
155             if (primaryCache != null) {
156                 if (primaryCache.size() < primaryCacheSize) {
157                     cached = primaryCache.offer(oldObject);
158                 }
159
160                 if (!cached && (secondaryCache.size() >= secondaryCacheHighWaterMark)) {
161                     // check for nulls in secondary cache and remove them to create room
162
Iterator JavaDoc<SoftReference JavaDoc<E>> it = secondaryCache.iterator();
163                     while (it.hasNext()) {
164                         SoftReference JavaDoc<E> sr = it.next();
165                         if (sr.get() == null) {
166                             it.remove();
167                         }
168                     }
169                 }
170
171                 if (!cached && (secondaryCache.size() < secondaryCacheHighWaterMark)) {
172                     cached = secondaryCache.offer(new SoftReference JavaDoc<E>(oldObject));
173                 }
174             }
175         }
176
177         return cached;
178     }
179 }
180
Popular Tags