diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/LongHashset.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/LongHashset.java index 2f8c2ccb3b..4422ec0797 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/LongHashset.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/LongHashset.java @@ -1,14 +1,27 @@ package org.bukkit.craftbukkit.util; -import static org.bukkit.craftbukkit.util.Java15Compat.Arrays_copyOf; -public class LongHashset extends LongHash { +import static org.bukkit.craftbukkit.util.Java15Compat.Arrays_copyOf; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + +public class LongHashset extends LongHash +{ long values[][][] = new long[256][][]; int count = 0; - + ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + ReadLock rl = rwl.readLock(); + WriteLock wl = rwl.writeLock(); + public boolean isEmpty() { - return count == 0; + rl.lock(); + try { + return count == 0; + } finally { + rl.unlock(); + } } - + public void add(int msw, int lsw) { add(toLong(msw, lsw)); } @@ -16,90 +29,142 @@ public class LongHashset extends LongHash { public void add(long key) { int mainIdx = (int) (key & 255); int outerIdx = (int) ((key >> 32) & 255); - long outer[][] = values[mainIdx], inner[]; - if(outer == null) values[mainIdx] = outer = new long[256][]; - inner = outer[outerIdx]; - if(inner == null) { - outer[outerIdx] = inner = new long[1]; - inner[0] = key; - count++; - } - else { - int i; - for(i = 0; i < inner.length; i++) { - if(inner[i] == key) { - return; + rl.lock(); + try { + wl.lock(); + try { + long outer[][] = values[mainIdx], inner[]; + if (outer == null) + values[mainIdx] = outer = new long[256][]; + inner = outer[outerIdx]; + if (inner == null) { + synchronized (this) { + outer[outerIdx] = inner = new long[1]; + inner[0] = key; + count++; + } + } else { + int i; + for (i = 0; i < inner.length; i++) { + if (inner[i] == key) { + return; + } + } + inner = Arrays_copyOf(inner, i + 1); + outer[outerIdx] = inner; + inner[i] = key; + count++; } + } finally { + wl.unlock(); } - outer[outerIdx] = inner = Arrays_copyOf(inner, i+1); - inner[i] = key; - count++; + } finally { + rl.unlock(); } } - + public boolean containsKey(long key) { int mainIdx = (int) (key & 255); int outerIdx = (int) ((key >> 32) & 255); - long outer[][] = values[mainIdx], inner[]; - if(outer == null) return false; - inner = outer[outerIdx]; - if(inner == null) return false; - else { - for(long entry : inner) { - if(entry == key) return true; - } - return false; - } - } - - public void remove(long key) { - long[][] outer = this.values[(int) (key & 255)]; - if (outer == null) return; - - long[] inner = outer[(int) ((key >> 32) & 255)]; - if (inner == null) return; - - int max = inner.length - 1; - for(int i = 0; i <= max; i++) { - if(inner[i] == key) { - count--; - if(i != max) { - inner[i] = inner[max]; + rl.lock(); + try { + long outer[][] = values[mainIdx], inner[]; + if (outer == null) + return false; + inner = outer[outerIdx]; + if (inner == null) + return false; + else { + for (long entry : inner) { + if (entry == key) + return true; } - outer[(int) ((key >> 32) & 255)] = (max == 0 ? null : Arrays_copyOf(inner, max)); - return; + return false; } + } finally { + rl.unlock(); } } - - public long popFirst() { - for(long[][] outer : values) { - if(outer == null) continue; - for(int i = 0; i < outer.length ; i++) { - long[] inner = outer[i]; - if(inner == null || inner.length == 0) continue; - count--; - long ret = inner[inner.length - 1]; - outer[i] = Arrays_copyOf(inner, inner.length - 1); - return ret; - + + public void remove(long key) { + rl.lock(); + try { + long[][] outer = this.values[(int) (key & 255)]; + if (outer == null) + return; + + long[] inner = outer[(int) ((key >> 32) & 255)]; + if (inner == null) + return; + + int max = inner.length - 1; + for (int i = 0; i <= max; i++) { + if (inner[i] == key) { + wl.lock(); + try { + count--; + if (i != max) { + inner[i] = inner[max]; + } + outer[(int) ((key >> 32) & 255)] = (max == 0 ? null : Arrays_copyOf(inner, max)); + } finally { + wl.unlock(); + } + return; + } } + } finally { + rl.unlock(); + } + } + + public long popFirst() { + rl.lock(); + try { + for (long[][] outer : values) { + if (outer == null) + continue; + for (int i = 0; i < outer.length; i++) { + long[] inner = outer[i]; + if (inner == null || inner.length == 0) + continue; + wl.lock(); + try { + count--; + long ret = inner[inner.length - 1]; + outer[i] = Arrays_copyOf(inner, inner.length - 1); + return ret; + } finally { + wl.unlock(); + } + + } + } + } finally { + rl.unlock(); } return 0; } - + public long[] keys() { int index = 0; - long ret[] = new long[count]; - for(long[][] outer : values) { - if(outer == null) continue; - for(long[] inner : outer) { - if(inner == null) continue; - for(long entry : inner) { - ret[index++] = entry; + rl.lock(); + try { + long ret[] = new long[count]; + for (long[][] outer : values) { + if (outer == null) + continue; + for (long[] inner : outer) { + if (inner == null) + continue; + for (long entry : inner) { + ret[index++] = entry; + } } } + return ret; + } finally { + rl.unlock(); } - return ret; } } \ No newline at end of file