2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.util;
20 import java.lang.ref.WeakReference;
23 * This is a simplified hash pool that does not support removal or
24 * numbering of elements.
26 public class WeakPool<E> {
27 private static final boolean DEBUG = false;
29 static final double MAX_LOAD_WIPE = 0.6;
30 static final double MAX_LOAD_REHASH = 0.4;
31 static final int DEFAULT_POW = 10;
33 WeakReference<E>[] table;
42 * Creates a SimplePool that holds about 716 elements before first
50 * Creates a SimplePool that holds about 0.7 * 2**pow elements before
53 public WeakPool(int pow) {
57 mask = table.length - 1;
58 nextWipe = (int)(MAX_LOAD_WIPE * mask);
59 nextRehash = (int)(MAX_LOAD_REHASH * mask);
62 @SuppressWarnings("unchecked")
63 protected void newTable() {
64 table = new WeakReference[1 << pow];
67 // ********************** API as simple hash pool ******************* //
70 * Asks whether a particular element is already pooled. NOT A TYPICAL
73 public boolean isPooled(E e) {
74 return e == null || query(e) != null;
78 * Returns the matching element if there is one, null if not.
81 if (e == null) return null;
82 int code = e.hashCode();
83 int idx = code & mask;
84 int delta = (code >> (pow - 1)) | 1; // must be odd!
88 WeakReference<E> r = table[idx];
91 if (o != null && e.equals(o)) {
92 return o; // seen before!
94 idx = (idx + delta) & mask;
95 assert (idx != oidx); // should never wrap around
101 * Returns a pooled element matching e, which will be e if no match
102 * has been previously pooled.
105 if (e == null) return null;
106 int code = e.hashCode();
107 int idx = code & mask;
108 int delta = (code >> (pow - 1)) | 1; // must be odd!
112 WeakReference<E> r = table[idx];
113 if (r == null) break;
115 if (o != null && e.equals(o)) {
116 return o; // seen before!
118 idx = (idx + delta) & mask;
119 assert (idx != oidx); // should never wrap around
121 assert (table[idx] == null); // should never fill up
122 // not seen before; add it
125 if (count >= nextWipe) { // too full
126 // determine if size needs to be increased or just wipe unused weak refs
127 int oldCount = count;
129 for (int i = 0; i < table.length; i++) {
130 if (table[i] != null && table[i].get() != null) {
134 if (DEBUG && oldCount > count) {
135 System.out.println("Weak references collected: " + (oldCount - count));
137 if (count >= nextRehash) {
138 pow++; // needs to be increased in size
140 WeakReference<E>[] oldTable = table;
142 mask = table.length - 1;
143 nextWipe = (int)(MAX_LOAD_WIPE * mask);
144 nextRehash = (int)(MAX_LOAD_REHASH * mask);
146 int oldLen = oldTable.length;
147 for (int i = 0; i < oldLen; i++) {
148 WeakReference<E> r = oldTable[i];
149 if (r == null) continue;
151 if (o == null) continue;
155 delta = (code >> (pow - 1)) | 1; // must be odd!
156 while (table[idx] != null) { // we know enough slots exist
157 idx = (idx + delta) & mask;
161 // done with rehash; now get idx to empty slot
164 delta = (code >> (pow - 1)) | 1; // must be odd!
165 while (table[idx] != null) { // we know enough slots exist & new element
166 idx = (idx + delta) & mask;
169 // idx already pointing to empty slot
172 table[idx] = new WeakReference<E>(e);
177 // ******************* API as add-only weak hash set *************** //
179 public boolean isMember(E e) {
180 return query(e) != null;
183 public void add(E e) {
188 // ************************** Test main ************************ //
193 public static void main(String[] args) {
194 WeakPool<Integer> pool = new WeakPool<Integer>(4);
195 for (int i = 0; i < 1000000; i += 42) {
196 Integer o = new Integer(i);
197 Integer p = pool.pool(o);
198 if (o != p) throw new RuntimeException();
199 Integer q = pool.pool(p);
200 if (q != p) throw new RuntimeException();
202 for (int i = 0; i < 1000000; i += 42) {
203 Integer o = new Integer(i);
204 Integer p = pool.pool(o);
205 if (o == p) throw new RuntimeException();
206 if (!o.equals(p)) throw new RuntimeException();
208 for (int i = 1; i < 1000000; i += 42) {
209 Integer o = new Integer(i);
210 Integer p = pool.pool(o);
211 if (o != p) throw new RuntimeException();