|
WeakBumpyStack |
|
1 /* 2 * Copyright (c) 1998-2001, The University of Sheffield. 3 * 4 * This file is part of GATE (see http://gate.ac.uk/), and is free 5 * software, licenced under the GNU Library General Public License, 6 * Version 2, June 1991 (in the distribution as file licence.html, 7 * and also available at http://gate.ac.uk/gate/licence.html). 8 * 9 * Valentin Tablan, 10/Oct/2001 10 * 11 * $Id: WeakBumpyStack.java,v 1.4 2001/11/24 18:23:24 hamish Exp $ 12 */ 13 14 //////////////////////////////////////////////////////////////////// 15 //////////// DEVELOPERS: SEE WARNING IN JAVADOC COMMENT FOR 16 //////////// THIS CLASS!!!! 17 //////////////////////////////////////////////////////////////////// 18 19 package gate.util; 20 21 import java.util.*; 22 import java.lang.ref.*; 23 24 import gate.*; 25 26 /** 27 * Weak stack that allow you to bump an element to the front. 28 * Objects that are only referenced by this stack will be candidates for 29 * garbage collection and wil be removed from the stack as soon as the garbage 30 * collector marks them for collection. 31 * <P> 32 * <B>*** WARNING: ***</B> the test for this class, 33 * <TT>TestBumpyStack.testSelfCleaning</TT> is not a proper test; it doesn't 34 * fail even when it should, and only prints a warning when DEBUG is true. 35 * This is because to test it properly you need to force garbage collection, 36 * and that isn't possible. So, if you work on this class <B>you must 37 * turn DEBUG on on TestBumpyStack</B> in order to run the tests in a 38 * meaningfull way. 39 */ 40 public class WeakBumpyStack extends AbstractList 41 { 42 43 /** 44 * Creates a new empty stack. 45 */ 46 public WeakBumpyStack(){ 47 supportStack = new Stack(); 48 refQueue = new ReferenceQueue(); 49 } 50 51 /** 52 * Pushes an item onto the top of this stack. This has exactly 53 * the same effect as: 54 * <blockquote><pre> 55 * addElement(item)</pre></blockquote> 56 * 57 * @param item the item to be pushed onto this stack. 58 * @return the <code>item</code> argument. 59 */ 60 public Object push(Object item){ 61 supportStack.push(new WeakReference(item,refQueue)); 62 return item; 63 } 64 65 /** 66 * Removes the object at the top of this stack and returns that 67 * object as the value of this function. 68 * 69 * @return The object at the top of this stack. 70 * @exception EmptyStackException if this stack is empty. 71 */ 72 public synchronized Object pop(){ 73 processQueue(); 74 //we need to check for null in case the top reference has just been cleared 75 Object res = null; 76 while(res == null){ 77 res = ((WeakReference)supportStack.pop()).get(); 78 } 79 return res; 80 } 81 82 83 /** 84 * Looks at the object at the top of this stack without removing it 85 * from the stack. 86 * 87 * @return the object at the top of this stack. 88 * @exception EmptyStackException if this stack is empty. 89 */ 90 public synchronized Object peek(){ 91 processQueue(); 92 //we need to check for null in case the top reference has just been cleared 93 Object res = null; 94 while(res == null){ 95 res = ((WeakReference)supportStack.peek()).get(); 96 } 97 return res; 98 } 99 100 /** 101 * Tests if this stack is empty. 102 * 103 * @return <code>true</code> if and only if this stack contains 104 * no items; <code>false</code> otherwise. 105 */ 106 public boolean empty() { 107 processQueue(); 108 return supportStack.empty(); 109 } 110 111 112 /** Bump an item to the front of the stack. 113 * @param item the item to bump 114 * @return true when the item was found, else false 115 */ 116 public boolean bump(Object item) { 117 processQueue(); 118 119 int itemIndex = search(item); 120 121 if(itemIndex == -1) // not a member of the stack 122 return false; 123 else if(itemIndex == 1) // at the front already 124 return true; 125 126 WeakReference wr = (WeakReference)supportStack.remove(itemIndex - 1); 127 supportStack.push(wr); 128 return true; 129 } // bump 130 131 /** 132 * Returns the 1-based position where an object is on this stack. 133 * If the object <tt>o</tt> occurs as an item in this stack, this 134 * method returns the distance from the top of the stack of the 135 * occurrence nearest the top of the stack; the topmost item on the 136 * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt> 137 * method is used to compare <tt>o</tt> to the 138 * items in this stack. 139 * 140 * @param o the desired object. 141 * @return the 1-based position from the top of the stack where 142 * the object is located; the return value <code>-1</code> 143 * indicates that the object is not on the stack. 144 */ 145 public synchronized int search(Object o) { 146 processQueue(); 147 int i = supportStack.size() - 1; 148 while(i >= 0 && 149 !((WeakReference)supportStack.get(i)).get().equals(o)) i--; 150 if (i >= 0) { 151 return supportStack.size() - i; 152 } 153 return -1; 154 } 155 156 157 /** 158 * Checks the queue for any new weak references that have been cleared and 159 * queued and removes them from the underlying stack. 160 * 161 * This method should be called by every public method before realising its 162 * internal logic. 163 */ 164 protected void processQueue(){ 165 WeakReference wr; 166 while ((wr = (WeakReference)refQueue.poll()) != null) { 167 supportStack.remove(wr); 168 } 169 } 170 171 /** 172 * Returns the element at the specified position in this list. 173 * 174 * @param index index of element to return. 175 * @return the element at the specified position in this list. 176 * @throws IndexOutOfBoundsException if index is out of range <tt>(index 177 * < 0 || index >= size())</tt>. 178 */ 179 public Object get(int index) { 180 processQueue(); 181 //we need to check for null in case the top reference has just been cleared 182 Object res = null; 183 while(res == null){ 184 res = ((WeakReference)supportStack.get(index)).get(); 185 } 186 return res; 187 } 188 189 /** 190 * Returns the number of elements in this list. 191 * 192 * @return the number of elements in this list. 193 */ 194 public int size() { 195 processQueue(); 196 return supportStack.size(); 197 } 198 199 /** 200 * Replaces the element at the specified position in this list with 201 * the specified element. 202 * 203 * @param index index of element to replace. 204 * @param element element to be stored at the specified position. 205 * @return the element previously at the specified position. 206 * @throws IndexOutOfBoundsException if index out of range 207 * <tt>(index < 0 || index >= size())</tt>. 208 */ 209 public Object set(int index, Object element) { 210 processQueue(); 211 WeakReference ref = (WeakReference) 212 supportStack.set(index, 213 new WeakReference(element, refQueue)); 214 return ref.get(); 215 } 216 217 /** 218 * Inserts the specified element at the specified position in this 219 * list. Shifts the element currently at that position (if any) and 220 * any subsequent elements to the right (adds one to their indices). 221 * 222 * @param index index at which the specified element is to be inserted. 223 * @param element element to be inserted. 224 * @throws IndexOutOfBoundsException if index is out of range 225 * <tt>(index < 0 || index > size())</tt>. 226 */ 227 public void add(int index, Object element) { 228 processQueue(); 229 supportStack.add(index, new WeakReference(element, refQueue)); 230 } 231 232 /** 233 * Removes the element at the specified position in this list. 234 * Shifts any subsequent elements to the left (subtracts one from their 235 * indices). 236 * 237 * @param index the index of the element to removed. 238 * @return the element that was removed from the list. 239 * @throws IndexOutOfBoundsException if index out of range <tt>(index 240 * < 0 || index >= size())</tt>. 241 */ 242 public Object remove(int index) { 243 processQueue(); 244 //we need to check for null in case the top reference has just been cleared 245 Object res = null; 246 while(res == null){ 247 res = ((WeakReference)supportStack.remove(index)).get(); 248 } 249 return res; 250 } 251 252 ReferenceQueue refQueue; 253 254 /** 255 * This is the underlying stack object for this weak stack. It holds weak 256 * references to the objects that are the actual contents of this stack. 257 */ 258 Stack supportStack; 259 } // class BumpyStack 260
|
WeakBumpyStack |
|