5 |
|
*/ |
6 |
|
|
7 |
|
package jsr166e; |
8 |
+ |
|
9 |
|
import java.util.Random; |
10 |
|
|
11 |
|
/** |
112 |
|
} |
113 |
|
|
114 |
|
/** |
115 |
< |
* Holder for the thread-local hash code. The code is initially |
116 |
< |
* random, but may be set to a different value upon collisions. |
117 |
< |
*/ |
118 |
< |
static final class HashCode { |
118 |
< |
static final Random rng = new Random(); |
119 |
< |
int code; |
120 |
< |
HashCode() { |
121 |
< |
int h = rng.nextInt(); // Avoid zero to allow xorShift rehash |
122 |
< |
code = (h == 0) ? 1 : h; |
123 |
< |
} |
124 |
< |
} |
125 |
< |
|
126 |
< |
/** |
127 |
< |
* The corresponding ThreadLocal class |
115 |
> |
* ThreadLocal holding a single-slot int array holding hash code. |
116 |
> |
* Unlike the JDK8 version of this class, we use a suboptimal |
117 |
> |
* int[] representation to avoid introducing a new type that can |
118 |
> |
* impede class-unloading when ThreadLocals are not removed. |
119 |
|
*/ |
120 |
< |
static final class ThreadHashCode extends ThreadLocal<HashCode> { |
130 |
< |
public HashCode initialValue() { return new HashCode(); } |
131 |
< |
} |
120 |
> |
static final ThreadLocal<int[]> threadHashCode = new ThreadLocal<int[]>(); |
121 |
|
|
122 |
|
/** |
123 |
< |
* Static per-thread hash codes. Shared across all instances to |
135 |
< |
* reduce ThreadLocal pollution and because adjustments due to |
136 |
< |
* collisions in one table are likely to be appropriate for |
137 |
< |
* others. |
123 |
> |
* Generator of new random hash codes |
124 |
|
*/ |
125 |
< |
static final ThreadHashCode threadHashCode = new ThreadHashCode(); |
125 |
> |
static final Random rng = new Random(); |
126 |
|
|
127 |
|
/** Number of CPUS, to place bound on table size */ |
128 |
|
static final int NCPU = Runtime.getRuntime().availableProcessors(); |
185 |
|
* @param hc the hash code holder |
186 |
|
* @param wasUncontended false if CAS failed before call |
187 |
|
*/ |
188 |
< |
final void retryUpdate(long x, HashCode hc, boolean wasUncontended) { |
189 |
< |
int h = hc.code; |
188 |
> |
final void retryUpdate(long x, int[] hc, boolean wasUncontended) { |
189 |
> |
int h; |
190 |
> |
if (hc == null) { |
191 |
> |
threadHashCode.set(hc = new int[1]); // Initialize randomly |
192 |
> |
int r = rng.nextInt(); // Avoid zero to allow xorShift rehash |
193 |
> |
h = hc[0] = (r == 0) ? 1 : r; |
194 |
> |
} |
195 |
> |
else |
196 |
> |
h = hc[0]; |
197 |
|
boolean collide = false; // True if last slot nonempty |
198 |
|
for (;;) { |
199 |
|
Cell[] as; Cell a; int n; long v; |
246 |
|
h ^= h << 13; // Rehash |
247 |
|
h ^= h >>> 17; |
248 |
|
h ^= h << 5; |
249 |
+ |
hc[0] = h; // Record index for next time |
250 |
|
} |
251 |
|
else if (busy == 0 && cells == as && casBusy()) { |
252 |
|
boolean init = false; |
266 |
|
else if (casBase(v = base, fn(v, x))) |
267 |
|
break; // Fall back on using base |
268 |
|
} |
275 |
– |
hc.code = h; // Record index for next time |
269 |
|
} |
270 |
|
|
271 |
|
|