1 10 11 20 24 package mondrian.util; 25 26 import java.util.Iterator ; 27 28 51 public class ObjectPool<T> { 52 protected static final byte FREE = 0; 59 protected static final byte FULL = 1; 60 61 protected static final int DEFAULT_CAPACITY = 277; 62 protected static final double DEFAULT_MIN_LOAD_FACTOR = 0.2; 63 protected static final double DEFAULT_MAX_LOAD_FACTOR = 0.5; 64 65 66 69 protected int distinct; 70 71 protected int lowWaterMark; 72 protected int highWaterMark; 73 74 77 protected double minLoadFactor; 78 79 82 protected double maxLoadFactor; 83 84 protected T[] values; 85 88 protected byte[] state; 89 90 93 protected int freeEntries; 94 95 96 97 public ObjectPool() { 98 this(DEFAULT_CAPACITY); 99 } 100 public ObjectPool(int initialCapacity) { 101 this(initialCapacity, DEFAULT_MIN_LOAD_FACTOR, DEFAULT_MAX_LOAD_FACTOR); 102 } 103 public ObjectPool(int initialCapacity, 104 double minLoadFactor, 105 double maxLoadFactor) { 106 setUp(initialCapacity,minLoadFactor,maxLoadFactor); 107 } 108 109 114 public int size() { 115 return distinct; 116 } 117 118 127 public void trimToSize() { 128 int newCapacity = nextPrime((int)(1 + 1.2*size())); 132 if (values.length > newCapacity) { 133 rehash(newCapacity); 134 } 135 } 136 137 144 public boolean contains(T key) { 145 int i = indexOfInsertion(key); 146 return (i < 0); 147 } 148 149 157 public T add(T key) { 158 int i = indexOfInsertion(key); 159 if (i < 0) { 160 i = -i -1; 162 return this.values[i]; 163 } 164 165 if (this.distinct > this.highWaterMark) { 166 int newCapacity = chooseGrowCapacity(this.distinct+1, 167 this.minLoadFactor, 168 this.maxLoadFactor); 169 rehash(newCapacity); 170 return add(key); 171 } 172 173 this.values[i] = key; 174 175 if (this.state[i] == FREE) { 176 this.freeEntries--; 177 } 178 this.state[i] = FULL; 179 this.distinct++; 180 181 if (this.freeEntries < 1) { 182 int newCapacity = chooseGrowCapacity(this.distinct+1, 184 this.minLoadFactor, 185 this.maxLoadFactor); 186 rehash(newCapacity); 187 } 188 189 return key; 190 } 191 192 196 public void clear() { 197 values = (T[]) new Object [values.length]; 198 state = new byte[state.length]; 199 200 this.distinct = 0; 201 this.freeEntries = values.length; trimToSize(); 203 } 204 205 213 public Iterator iterator() { 214 return new Itr(); 215 } 216 217 218 219 protected int chooseGrowCapacity(int size, double minLoad, double maxLoad) { 220 return nextPrime(Math.max(size+1, 221 (int) ((4*size / (3*minLoad+maxLoad))))); 222 } 223 protected int chooseHighWaterMark(int capacity, double maxLoad) { 224 return Math.min(capacity-2, (int) (capacity * maxLoad)); 226 } 227 protected int chooseLowWaterMark(int capacity, double minLoad) { 228 return (int) (capacity * minLoad); 229 } 230 protected int chooseMeanCapacity(int size, double minLoad, double maxLoad) { 231 return nextPrime(Math.max(size+1, (int) ((2*size/(minLoad+maxLoad))))); 232 } 233 protected int chooseShrinkCapacity(int size, double minLoad, double maxLoad) { 234 return nextPrime(Math.max(size+1, (int) ((4*size/(minLoad+3*maxLoad))))); 235 } 236 237 protected int nextPrime(int desiredCapacity) { 238 return PrimeFinder.nextPrime(desiredCapacity); 239 } 240 241 protected void setUp(int initialCapacity, 242 double minLoadFactor, 243 double maxLoadFactor) { 244 int capacity = initialCapacity; 245 246 if (initialCapacity < 0) { 247 throw new IllegalArgumentException ( 248 "Initial Capacity must not be less than zero: "+ 249 initialCapacity); 250 } 251 if (minLoadFactor < 0.0 || minLoadFactor >= 1.0) { 252 throw new IllegalArgumentException ( 253 "Illegal minLoadFactor: "+ minLoadFactor); 254 } 255 if (maxLoadFactor <= 0.0 || maxLoadFactor >= 1.0) { 256 throw new IllegalArgumentException ( 257 "Illegal maxLoadFactor: "+ maxLoadFactor); 258 } 259 if (minLoadFactor >= maxLoadFactor) { 260 throw new IllegalArgumentException ( 261 "Illegal minLoadFactor: "+ minLoadFactor+ 262 " and maxLoadFactor: "+ maxLoadFactor); 263 } 264 capacity = nextPrime(capacity); 265 266 if (capacity == 0) { 268 capacity = 1; 269 } 270 271 this.values = (T[]) new Object [capacity]; 273 this.state = new byte[capacity]; 274 275 this.minLoadFactor = minLoadFactor; 278 if (capacity == PrimeFinder.largestPrime) { 279 this.maxLoadFactor = 1.0; 280 } else { 281 this.maxLoadFactor = maxLoadFactor; 282 } 283 284 this.distinct = 0; 285 this.freeEntries = capacity; this.lowWaterMark = 0; 293 this.highWaterMark = chooseHighWaterMark(capacity, this.maxLoadFactor); 294 295 } 296 297 298 protected int hash(T key) { 299 return (key == null) ? 0 : key.hashCode(); 300 } 301 protected boolean equals(T t, T key) { 302 return (t != null) && t.equals(key); 303 } 304 305 protected int indexOfInsertion(T key) { 306 final T[] tab = values; 307 final byte[] stat = state; 308 final int length = tab.length; 309 310 final int hash = hash(key) & 0x7FFFFFFF; 311 int i = hash % length; 312 313 int decrement = hash % (length-2); 316 317 if (decrement == 0) { 319 decrement = 1; 320 } 321 322 while ((stat[i] == FULL) && !equals(tab[i], key)) { 324 i -= decrement; 325 if (i < 0) { 327 i += length; 328 } 329 } 330 331 return (stat[i] == FULL) ? -i-1 : i; 336 } 337 338 protected void rehash(int newCapacity) { 339 int oldCapacity = values.length; 340 341 T[] oldValues = values; 342 byte[] oldState = state; 343 344 T[] newValues = (T[]) new Object [newCapacity]; 345 byte[] newState = new byte[newCapacity]; 346 347 this.lowWaterMark = chooseLowWaterMark(newCapacity,this.minLoadFactor); 348 this.highWaterMark = chooseHighWaterMark(newCapacity,this.maxLoadFactor); 349 350 this.values = newValues; 351 this.state = newState; 352 this.freeEntries = newCapacity-this.distinct; for (int i = oldCapacity ; i-- > 0 ;) { 354 if (oldState[i]==FULL) { 355 T element = oldValues[i]; 356 int index = indexOfInsertion(element); 357 newValues[index]=element; 358 newState[index]=FULL; 359 } 360 } 361 } 362 363 private class Itr implements Iterator <T> { 364 int index = 0; 365 Itr() { 366 } 367 public boolean hasNext() { 368 if (index == ObjectPool.this.state.length) { 369 return false; 370 } 371 while (ObjectPool.this.state[index] != FULL) { 372 index++; 373 if (index == ObjectPool.this.state.length) { 374 return false; 375 } 376 } 377 return (ObjectPool.this.state[index] == FULL); 378 } 379 public T next() { 380 return ObjectPool.this.values[index++]; 381 } 382 public void remove() { 383 throw new UnsupportedOperationException ("ObjectPool.Itr.remove"); 384 } 385 } 386 } 387 388 | Popular Tags |