1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util.internal;
17
18 import java.util.Arrays;
19
20 public final class LongLongHashMap {
21 private static final int MASK_TEMPLATE = ~1;
22 private int mask;
23 private long[] array;
24 private int maxProbe;
25 private long zeroVal;
26 private final long emptyVal;
27
28 public LongLongHashMap(long emptyVal) {
29 this.emptyVal = emptyVal;
30 zeroVal = emptyVal;
31 int initialSize = 32;
32 array = new long[initialSize];
33 mask = initialSize - 1;
34 computeMaskAndProbe();
35 }
36
37 public LongLongHashMap(LongLongHashMap other) {
38 this.mask = other.mask;
39 this.array = Arrays.copyOf(other.array, other.array.length);
40 this.maxProbe = other.maxProbe;
41 this.zeroVal = other.zeroVal;
42 this.emptyVal = other.emptyVal;
43 }
44
45 public long put(long key, long value) {
46 if (key == 0) {
47 long prev = zeroVal;
48 zeroVal = value;
49 return prev;
50 }
51
52 for (;;) {
53 int index = index(key);
54 for (int i = 0; i < maxProbe; i++) {
55 long existing = array[index];
56 if (existing == key || existing == 0) {
57 long prev = existing == 0? emptyVal : array[index + 1];
58 array[index] = key;
59 array[index + 1] = value;
60 for (; i < maxProbe; i++) {
61 index = index + 2 & mask;
62 if (array[index] == key) {
63 array[index] = 0;
64 prev = array[index + 1];
65 break;
66 }
67 }
68 return prev;
69 }
70 index = index + 2 & mask;
71 }
72 expand();
73 }
74 }
75
76 public void remove(long key) {
77 if (key == 0) {
78 zeroVal = emptyVal;
79 return;
80 }
81 int index = index(key);
82 for (int i = 0; i < maxProbe; i++) {
83 long existing = array[index];
84 if (existing == key) {
85 array[index] = 0;
86 break;
87 }
88 index = index + 2 & mask;
89 }
90 }
91
92 public long get(long key) {
93 if (key == 0) {
94 return zeroVal;
95 }
96 int index = index(key);
97 for (int i = 0; i < maxProbe; i++) {
98 long existing = array[index];
99 if (existing == key) {
100 return array[index + 1];
101 }
102 index = index + 2 & mask;
103 }
104 return emptyVal;
105 }
106
107 private int index(long key) {
108
109 key ^= key >>> 33;
110 key *= 0xff51afd7ed558ccdL;
111 key ^= key >>> 33;
112 key *= 0xc4ceb9fe1a85ec53L;
113 key ^= key >>> 33;
114 return (int) key & mask;
115 }
116
117 private void expand() {
118 long[] prev = array;
119 array = new long[prev.length * 2];
120 computeMaskAndProbe();
121 for (int i = 0; i < prev.length; i += 2) {
122 long key = prev[i];
123 if (key != 0) {
124 long val = prev[i + 1];
125 put(key, val);
126 }
127 }
128 }
129
130 private void computeMaskAndProbe() {
131 int length = array.length;
132 mask = length - 1 & MASK_TEMPLATE;
133 maxProbe = (int) Math.log(length);
134 }
135 }