comparison src/main/gov/nasa/jpf/util/SimplePool.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
1 /*
2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
4 * All rights reserved.
5 *
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
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0.
11 *
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.
17 */
18 package gov.nasa.jpf.util;
19
20 /**
21 * This is a simplified hash pool that does not support removal or
22 * numbering of elements.
23 */
24 @SuppressWarnings("unchecked")
25 public class SimplePool<E> {
26 static final double MAX_LOAD = 0.7;
27 static final int DEFAULT_POW = 10;
28
29 Object[] table;
30
31 int count;
32 int pow;
33 int mask;
34 int nextRehash;
35
36 /**
37 * Creates a SimplePool that holds about 716 elements before first
38 * rehash.
39 */
40 public SimplePool() {
41 this(DEFAULT_POW);
42 }
43
44 /**
45 * Creates a SimplePool that holds about 0.7 * 2**pow elements before
46 * first rehash.
47 */
48 public SimplePool(int pow) {
49 table = new Object[1 << pow];
50 count = 0;
51 this.pow = pow;
52 mask = table.length - 1;
53 nextRehash = (int)(MAX_LOAD * mask);
54 }
55
56 // ********************** API as simple hash pool ******************* //
57
58 /**
59 * Asks whether a particular element is already pooled. NOT A TYPICAL
60 * OPERATION.
61 */
62 public boolean isPooled(E e) {
63 return e == null || query(e) != null;
64 }
65
66 /**
67 * Returns the matching element if there is one, null if not.
68 */
69 public E query(E e) {
70 if (e == null) return null;
71 int code = e.hashCode();
72 int idx = code & mask;
73 int delta = (code >> (pow - 1)) | 1; // must be odd!
74 int oidx = idx;
75
76 for(;;) {
77 Object o = table[idx];
78 if (o == null) break;
79 if (e.equals(o)) {
80 return (E) o; // seen before!
81 }
82 idx = (idx + delta) & mask;
83 assert (idx != oidx); // should never wrap around
84 }
85 return null;
86 }
87
88 /**
89 * Returns a pooled element matching e, which will be e if no match
90 * has been previously pooled.
91 */
92 public E pool(E e) {
93 if (e == null) return null;
94 int code = e.hashCode();
95 int idx = code & mask;
96 int delta = (code >> (pow - 1)) | 1; // must be odd!
97 int oidx = idx;
98
99 for(;;) {
100 Object o = table[idx];
101 if (o == null) break;
102 if (e.equals(o)) {
103 return (E) o; // seen before!
104 }
105 idx = (idx + delta) & mask;
106 assert (idx != oidx); // should never wrap around
107 }
108 assert (table[idx] == null); // should never fill up
109 // not seen before; add it
110
111 count++;
112 if (count >= nextRehash) { // too full
113 Object[] oldTable = table;
114 pow++;
115 table = new Object[1 << pow];
116 mask = table.length - 1;
117 nextRehash = (int)(MAX_LOAD * mask);
118
119 int oldLen = oldTable.length;
120 for (int i = 0; i < oldLen; i++) {
121 Object o = oldTable[i];
122 if (o != null) {
123 code = o.hashCode();
124 idx = code & mask;
125 delta = (code >> (pow - 1)) | 1; // must be odd!
126 while (table[idx] != null) { // we know enough slots exist
127 idx = (idx + delta) & mask;
128 }
129 table[idx] = o;
130 }
131 }
132 // done with rehash; now get idx to empty slot
133 code = e.hashCode();
134 idx = code & mask;
135 delta = (code >> (pow - 1)) | 1; // must be odd!
136 while (table[idx] != null) { // we know enough slots exist & new element
137 idx = (idx + delta) & mask;
138 }
139 } else {
140 // idx already pointing to empty slot
141 }
142
143 table[idx] = e;
144 return e;
145 }
146
147
148 // ******************* API as add-only hash set *************** //
149
150 public boolean isMember(E e) {
151 return query(e) != null;
152 }
153
154 public void add(E e) {
155 /*(void)*/ pool(e);
156 }
157
158
159 // ************************** Test main ************************ //
160
161 /**
162 * Test main.
163 */
164 public static void main(String[] args) {
165 SimplePool<Integer> pool = new SimplePool<Integer>(4);
166 for (int i = 0; i < 1000000; i += 42) {
167 Integer o = new Integer(i);
168 Integer p = pool.pool(o);
169 if (o != p) throw new RuntimeException();
170 Integer q = pool.pool(p);
171 if (q != p) throw new RuntimeException();
172 }
173 for (int i = 0; i < 1000000; i += 42) {
174 Integer o = new Integer(i);
175 Integer p = pool.pool(o);
176 if (o == p) throw new RuntimeException();
177 if (!o.equals(p)) throw new RuntimeException();
178 }
179 for (int i = 1; i < 1000000; i += 42) {
180 Integer o = new Integer(i);
181 Integer p = pool.pool(o);
182 if (o != p) throw new RuntimeException();
183 }
184 }
185 }