Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
1package org.bukkit.craftbukkit.util;
2
3import java.util.concurrent.locks.ReentrantReadWriteLock;
4import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
5import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
6
7import static org.bukkit.craftbukkit.util.Java15Compat.Arrays_copyOf;
8
9public class LongHashset extends LongHash {
10 long[][][] values = new long[256][][];
11 int count = 0;
12 ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
13 ReadLock rl = rwl.readLock();
14 WriteLock wl = rwl.writeLock();
15
16 public boolean isEmpty() {
17 rl.lock();
18 try {
19 return this.count == 0;
20 } finally {
21 rl.unlock();
22 }
23 }
24
25 public void add(int msw, int lsw) {
26 add(toLong(msw, lsw));
27 }
28
29 public void add(long key) {
30 wl.lock();
31 try {
32 int mainIdx = (int) (key & 255);
33 long outer[][] = this.values[mainIdx];
34 if (outer == null) this.values[mainIdx] = outer = new long[256][];
35
36 int outerIdx = (int) ((key >> 32) & 255);
37 long inner[] = outer[outerIdx];
38
39 if (inner == null) {
40 synchronized (this) {
41 outer[outerIdx] = inner = new long[1];
42 inner[0] = key;
43 this.count++;
44 }
45 } else {
46 int i;
47 for (i = 0; i < inner.length; i++) {
48 if (inner[i] == key) {
49 return;
50 }
51 }
52 inner = Arrays_copyOf(inner, i + 1);
53 outer[outerIdx] = inner;
54 inner[i] = key;
55 this.count++;
56 }
57 } finally {
58 wl.unlock();
59 }
60 }
61
62 public boolean containsKey(long key) {
63 rl.lock();
64 try {
65 long[][] outer = this.values[(int) (key & 255)];
66 if (outer == null) return false;
67
68 long[] inner = outer[(int) ((key >> 32) & 255)];
69 if (inner == null) return false;
70
71 for (long entry : inner) {
72 if (entry == key) return true;
73 }
74 return false;
75 } finally {
76 rl.unlock();
77 }
78 }
79
80 public void remove(long key) {
81 wl.lock();
82 try {
83 long[][] outer = this.values[(int) (key & 255)];
84 if (outer == null) return;
85
86 long[] inner = outer[(int) ((key >> 32) & 255)];
87 if (inner == null) return;
88
89 int max = inner.length - 1;
90 for (int i = 0; i <= max; i++) {
91 if (inner[i] == key) {
92 this.count--;
93 if (i != max) {
94 inner[i] = inner[max];
95 }
96
97 outer[(int) ((key >> 32) & 255)] = (max == 0 ? null : Arrays_copyOf(inner, max));
98 return;
99 }
100 }
101 } finally {
102 wl.unlock();
103 }
104 }
105
106 public long popFirst() {
107 wl.lock();
108 try {
109 for (long[][] outer : this.values) {
110 if (outer == null) continue;
111
112 for (int i = 0; i < outer.length; i++) {
113 long[] inner = outer[i];
114 if (inner == null || inner.length == 0) continue;
115
116 this.count--;
117 long ret = inner[inner.length - 1];
118 outer[i] = Arrays_copyOf(inner, inner.length - 1);
119
120 return ret;
121 }
122 }
123 } finally {
124 wl.unlock();
125 }
126 return 0;
127 }
128
129 public long[] keys() {
130 int index = 0;
131 rl.lock();
132 try {
133 long[] ret = new long[this.count];
134 for (long[][] outer : this.values) {
135 if (outer == null) continue;
136
137 for (long[] inner : outer) {
138 if (inner == null) continue;
139
140 for (long entry : inner) {
141 ret[index++] = entry;
142 }
143 }
144 }
145 return ret;
146 } finally {
147 rl.unlock();
148 }
149 }
150}