From 4a30b6d2645ea608891984afeb1fb44417229e2f Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Tue, 5 Jan 2021 18:48:55 -0500 Subject: [PATCH] Locking --- pom.xml | 2 +- src/main/java/com/volmit/iris/Iris.java | 1 + .../com/volmit/iris/generator/IrisEngine.java | 2 +- .../manager/command/CommandIrisCreate.java | 11 ++ .../iris/manager/link/MultiverseCoreLink.java | 5 + .../com/volmit/iris/pregen/Pregenerator.java | 6 +- .../engine/EngineParallaxManager.java | 90 +++++----- .../scaffold/hunk/io/HunkRegionSlice.java | 167 +++++++++++------- .../scaffold/parallax/ParallaxRegion.java | 44 +++-- .../iris/scaffold/parallax/ParallaxWorld.java | 46 ++--- .../iris/scaffold/parallel/GridLock.java | 89 +++++++++- .../java/com/volmit/iris/util/IORunnable.java | 6 +- 12 files changed, 306 insertions(+), 163 deletions(-) diff --git a/pom.xml b/pom.xml index 87117c1e8..388a7dad1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.volmit Iris - 1.2.3 + 1.2.4-hotfix1 Iris false diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index ab5040801..0ca049413 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -292,6 +292,7 @@ public class Iris extends VolmitPlugin @Override public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { + //TODO: Support ID try { return INMS.get().createWorld(new IrisWorldCreator() diff --git a/src/main/java/com/volmit/iris/generator/IrisEngine.java b/src/main/java/com/volmit/iris/generator/IrisEngine.java index c55e3ad38..514179c01 100644 --- a/src/main/java/com/volmit/iris/generator/IrisEngine.java +++ b/src/main/java/com/volmit/iris/generator/IrisEngine.java @@ -107,7 +107,7 @@ public class IrisEngine extends BlockPopulator implements Engine Hunk blocks = vblocks.synchronize().listen((xx,y,zz,t) -> catchBlockUpdates(x+xx,y+getMinHeight(),z+zz, t)); Hunk pblocks = structures ? postblocks.synchronize().listen((xx,y,zz,t) -> catchBlockUpdates(x+xx,y+getMinHeight(),z+zz, t)) : null; Hunk fringe = structures ? Hunk.fringe(blocks, pblocks) : null; - getFramework().getEngineParallax().generateParallaxArea(x, z); + getFramework().getEngineParallax().generateParallaxArea(x>>4, z>>4); getFramework().getBiomeActuator().actuate(x, z, vbiomes); getFramework().getTerrainActuator().actuate(x, z, blocks); getFramework().getCaveModifier().modify(x, z, blocks); diff --git a/src/main/java/com/volmit/iris/manager/command/CommandIrisCreate.java b/src/main/java/com/volmit/iris/manager/command/CommandIrisCreate.java index 50a257ccf..2a98ca8f0 100644 --- a/src/main/java/com/volmit/iris/manager/command/CommandIrisCreate.java +++ b/src/main/java/com/volmit/iris/manager/command/CommandIrisCreate.java @@ -2,6 +2,7 @@ package com.volmit.iris.manager.command; import com.volmit.iris.Iris; import com.volmit.iris.manager.IrisDataManager; +import com.volmit.iris.manager.link.MultiverseCoreLink; import com.volmit.iris.nms.INMS; import com.volmit.iris.object.IrisDimension; import com.volmit.iris.pregen.Pregenerator; @@ -58,6 +59,16 @@ public class CommandIrisCreate extends MortarCommand if(multiverse) { dim = IrisDataManager.loadAnyDimension(type); + if(dim.getEnvironment() == null) + { + dim.setEnvironment(World.Environment.NORMAL); + } + + if(Iris.linkMultiverseCore == null) + { + Iris.linkMultiverseCore = new MultiverseCoreLink(); + } + String command = "mv create " + worldName + " " + Iris.linkMultiverseCore.envName(dim.getEnvironment()); command += " -s " + seed; command += " -g Iris"; diff --git a/src/main/java/com/volmit/iris/manager/link/MultiverseCoreLink.java b/src/main/java/com/volmit/iris/manager/link/MultiverseCoreLink.java index 1801a1907..656f7f9b1 100644 --- a/src/main/java/com/volmit/iris/manager/link/MultiverseCoreLink.java +++ b/src/main/java/com/volmit/iris/manager/link/MultiverseCoreLink.java @@ -133,6 +133,11 @@ public class MultiverseCoreLink } public String envName(World.Environment environment) { + if(environment == null) + { + return "normal"; + } + switch(environment) { case NORMAL: diff --git a/src/main/java/com/volmit/iris/pregen/Pregenerator.java b/src/main/java/com/volmit/iris/pregen/Pregenerator.java index df1497b10..5b1c894da 100644 --- a/src/main/java/com/volmit/iris/pregen/Pregenerator.java +++ b/src/main/java/com/volmit/iris/pregen/Pregenerator.java @@ -1,6 +1,5 @@ package com.volmit.iris.pregen; -import com.sun.javafx.scene.control.skin.TableHeaderRow; import com.volmit.iris.Iris; import com.volmit.iris.IrisSettings; import com.volmit.iris.scaffold.IrisWorlds; @@ -201,6 +200,11 @@ public class Pregenerator implements Listener } private boolean generateMCARegion(int x, int z, MultiBurst burst, IrisAccess access, Consumer3> mcaIteration) { + if(!Iris.instance.isMCA()) + { + return false; + } + File mca = new File(world.getWorldFolder(), "region/r." + x + "." + z + ".mca"); File mcg = directWriter.getMCAFile(x, z); Path fileToMovePath = Paths.get(mcg.toURI()); diff --git a/src/main/java/com/volmit/iris/scaffold/engine/EngineParallaxManager.java b/src/main/java/com/volmit/iris/scaffold/engine/EngineParallaxManager.java index a7d44a55e..d204aa318 100644 --- a/src/main/java/com/volmit/iris/scaffold/engine/EngineParallaxManager.java +++ b/src/main/java/com/volmit/iris/scaffold/engine/EngineParallaxManager.java @@ -160,40 +160,6 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer { } } - default void generateParallaxAreaFeatures(int x, int z) { - try { - PrecisionStopwatch p = PrecisionStopwatch.start(); - int s = (int) Math.ceil(getParallaxSize() / 2D); - int i, j; - - for (i = -s; i <= s; i++) { - int ii = i; - for (j = -s; j <= s; j++) { - int jj = j; - - int xxx = ((ii * 16) + (x)); - int zzz = ((jj * 16) + (z)); - int xx = xxx >> 4; - int zz = zzz >> 4; - - if (!getParallaxAccess().isFeatureGenerated(xx, zz)){ - RNG rng = new RNG(Cache.key(xx, zz)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed()); - IrisRegion region = getComplex().getRegionStream().get(xxx, zzz); - IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz); - generateParallaxFeatures(rng, xx, zz, region, biome); - getParallaxAccess().setFeatureGenerated(xx, zz); - } - } - } - - p.end(); - getEngine().getMetrics().getParallax().put(p.getMilliseconds()); - } catch (Throwable e) { - Iris.error("Failed to generate parallax in " + x + " " + z); - e.printStackTrace(); - } - } - default void forEachFeature(double x, double z, Consumer f) { for(IrisFeaturePositional i : getEngine().getDimension().getSpecificFeatures()) @@ -228,26 +194,50 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer { } } + default void generateParallaxAreaFeatures(int x, int z) { + try { + int s = (int) Math.ceil(getParallaxSize() / 2D); + int i, j; + + for (i = -s; i <= s; i++) { + for (j = -s; j <= s; j++) { + int xx = i +x; + int zz = j +z; + int xxx = xx << 4; + int zzz = zz << 4; + + if (!getParallaxAccess().isFeatureGenerated(xx, zz)){ + getParallaxAccess().setFeatureGenerated(xx, zz); + RNG rng = new RNG(Cache.key(xx, zz)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed()); + IrisRegion region = getComplex().getRegionStream().get(xxx, zzz); + IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz); + generateParallaxFeatures(rng, xx, zz, region, biome); + } + } + } + + } catch (Throwable e) { + Iris.error("Failed to generate parallax in " + x + " " + z); + e.printStackTrace(); + } + } + default void generateParallaxArea(int x, int z) { try { PrecisionStopwatch p = PrecisionStopwatch.start(); + generateParallaxAreaFeatures(x, z); int s = (int) Math.ceil(getParallaxSize() / 2D); int i,j; - generateParallaxAreaFeatures(x, z); - for(i = -s; i <= s; i++) - { - int ii = i; - for(j = -s; j <= s; j++) - { - int jj = j; - generateParallaxLayer((ii*16)+x, (jj*16)+z); + for (i = -s; i <= s; i++) { + for (j = -s; j <= s; j++) { + generateParallaxLayer(i +x, j +z); } } - getParallaxAccess().setChunkGenerated(x>>4, z>>4); + getParallaxAccess().setChunkGenerated(x, z); p.end(); getEngine().getMetrics().getParallax().put(p.getMilliseconds()); } @@ -261,18 +251,20 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer { default void generateParallaxLayer(int x, int z, boolean force) { - if(!force && getParallaxAccess().isParallaxGenerated(x >> 4, z >> 4)) + if(!force && getParallaxAccess().isParallaxGenerated(x, z)) { return; } - getParallaxAccess().setParallaxGenerated(x>>4, z>>4); + int xx = x<<4; + int zz = z<<4; + getParallaxAccess().setParallaxGenerated(x, z); RNG rng = new RNG(Cache.key(x, z)).nextParallelRNG(getEngine().getTarget().getWorld().getSeed()); - IrisRegion region = getComplex().getRegionStream().get(x+8, z+8); - IrisBiome biome = getComplex().getTrueBiomeStream().get(x+8, z+8); + IrisRegion region = getComplex().getRegionStream().get(xx+8, zz+8); + IrisBiome biome = getComplex().getTrueBiomeStream().get(xx+8, zz+8); generateParallaxSurface(rng, x, z, biome); generateParallaxMutations(rng, x, z); - generateStructures(rng, x>>4, z>>4, region, biome); + generateStructures(rng, x, z, region, biome); } default void generateParallaxFeatures(RNG rng, int cx, int cz, IrisRegion region, IrisBiome biome) @@ -372,7 +364,7 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer { { if(rng.chance(i.getChance()) && rng.chance(getComplex().getObjectChanceStream().get(x, z))) { - place(rng, x, z, i); + place(rng, x<<4, z<<4, i); } } } diff --git a/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java b/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java index c3ba3aa2f..d50c206e3 100644 --- a/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java +++ b/src/main/java/com/volmit/iris/scaffold/hunk/io/HunkRegionSlice.java @@ -3,11 +3,13 @@ package com.volmit.iris.scaffold.hunk.io; import com.volmit.iris.Iris; import com.volmit.iris.scaffold.hunk.Hunk; import com.volmit.iris.scaffold.parallel.BurstExecutor; +import com.volmit.iris.scaffold.parallel.GridLock; import com.volmit.iris.scaffold.parallel.MultiBurst; import com.volmit.iris.util.*; import org.bukkit.block.data.BlockData; import java.io.IOException; +import java.util.concurrent.atomic.AtomicReference; public class HunkRegionSlice { @@ -15,6 +17,7 @@ public class HunkRegionSlice public static final Function3> STRING = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newAtomicHunk, new StringHunkIOAdapter(), c, t); public static final Function3> BOOLEAN = (h, c, t) -> new HunkRegionSlice<>(h, Hunk::newAtomicHunk, new BooleanHunkIOAdapter(), c, t); private final Function3> factory; + private final GridLock lock; private final HunkIOAdapter adapter; private final CompoundTag compound; private final String key; @@ -25,6 +28,7 @@ public class HunkRegionSlice public HunkRegionSlice(int height, Function3> factory, HunkIOAdapter adapter, CompoundTag compound, String key) { + this.lock = new GridLock(32, 32); this.height = height; this.loadedChunks = new KMap<>(); this.factory = factory; @@ -35,7 +39,7 @@ public class HunkRegionSlice this.lastUse = new KMap<>(); } - public int cleanup(long t) + public synchronized int cleanup(long t) { int v = 0; if(loadedChunks.size() != lastUse.size()) @@ -64,7 +68,7 @@ public class HunkRegionSlice return v; } - public void clear() + public synchronized void clear() { for(String i : new KList<>(compound.getValue().keySet())) { @@ -75,7 +79,7 @@ public class HunkRegionSlice } } - public void save() + public synchronized void save() { BurstExecutor e = MultiBurst.burst.burst(); for(ChunkPosition i : save.copy()) @@ -89,7 +93,7 @@ public class HunkRegionSlice try { - save.remove(i); + lock.withNasty(i.getX(), i.getZ(), () -> save.remove(i)); } catch(Throwable ef) @@ -101,35 +105,56 @@ public class HunkRegionSlice e.complete(); } - public boolean contains(int x, int z) + public boolean contains(int x, int z) { return compound.getValue().containsKey(key(x, z)); } - public void delete(int x, int z) + public void delete(int x, int z) { - compound.getValue().remove(key(x, z)); + lock.with(x, z, () -> compound.getValue().remove(key(x, z))); } - public Hunk read(int x, int z) throws IOException + public Hunk read(int x, int z) throws IOException { - Tag t = compound.getValue().get(key(x, z)); + AtomicReference e = new AtomicReference<>(); + Hunk xt = lock.withResult(x, z, () -> { + Tag t = compound.getValue().get(key(x, z)); + + if(!(t instanceof ByteArrayTag)) + { + Iris.verbose("NOT BYTE ARRAY!"); + return null; + } + + try { + return adapter.read(factory, (ByteArrayTag) t); + } catch (IOException xe) { + e.set(xe); + } - if(!(t instanceof ByteArrayTag)) - { - Iris.verbose("NOT BYTE ARRAY!"); return null; + }); + + if(xt != null) + { + return xt; } - return adapter.read(factory, (ByteArrayTag) t); + if(e.get()!= null) + { + throw e.get(); + } + + return null; } - public void write(Hunk hunk, int x, int z) throws IOException + public void write(Hunk hunk, int x, int z) throws IOException { - compound.getValue().put(key(x, z), hunk.writeByteArrayTag(adapter, key(x, z))); + lock.withIO(x, z, () -> compound.getValue().put(key(x, z), hunk.writeByteArrayTag(adapter, key(x, z)))); } - public int unloadAll() + public synchronized int unloadAll() { int v = 0; for(ChunkPosition i : loadedChunks.k()) @@ -148,7 +173,7 @@ public class HunkRegionSlice { try { - write(region, x, z); + lock.withIO(x, z, () -> write(region, x, z)); } catch(IOException e) { @@ -156,92 +181,102 @@ public class HunkRegionSlice } } - public boolean isLoaded(int x, int z) + public boolean isLoaded(int x, int z) { - return loadedChunks.containsKey(new ChunkPosition(x, z)); + return lock.withResult(x, z, () -> loadedChunks.containsKey(new ChunkPosition(x, z))); } public void save(int x, int z) { - if(isLoaded(x, z)) - { - save(get(x, z), x, z); - } + lock.with(x, z, () -> { + if(isLoaded(x, z)) + { + save(get(x, z), x, z); + } + }); } - public void unload(int x, int z) + public void unload(int x, int z) { - ChunkPosition key = new ChunkPosition(x, z); - if(isLoaded(x, z)) - { - if(save.contains(key)) + lock.with(x, z, () -> { + ChunkPosition key = new ChunkPosition(x, z); + if(isLoaded(x, z)) { - save(x, z); - save.remove(key); - } + if(save.contains(key)) + { + save(x, z); + save.remove(key); + } - lastUse.remove(key); - loadedChunks.remove(key); - } + lastUse.remove(key); + loadedChunks.remove(key); + } + }); } public Hunk load(int x, int z) { - if(isLoaded(x, z)) - { - return loadedChunks.get(new ChunkPosition(x, z)); - } - - Hunk v = null; - - if(contains(x, z)) - { - try + return lock.withResult(x, z, () -> { + if(isLoaded(x, z)) { - v = read(x, z); + return loadedChunks.get(new ChunkPosition(x, z)); } - catch(IOException e) + Hunk v = null; + + if(contains(x, z)) { - e.printStackTrace(); + try + { + v = read(x, z); + } + + catch(IOException e) + { + e.printStackTrace(); + } } - } - if(v == null) - { - v = factory.apply(16, height, 16); - } + if(v == null) + { + v = factory.apply(16, height, 16); + } - loadedChunks.put(new ChunkPosition(x, z), v); + loadedChunks.put(new ChunkPosition(x, z), v); - return v; + return v; + }); } public Hunk get(int x, int z) { - ChunkPosition key = new ChunkPosition(x, z); + return lock.withResult(x, z, () -> { + ChunkPosition key = new ChunkPosition(x, z); - Hunk c = loadedChunks.get(key); + Hunk c = loadedChunks.get(key); - if(c == null) - { - c = load(x, z); - } + if(c == null) + { + c = load(x, z); + } - lastUse.put(new ChunkPosition(x, z), M.ms()); + lastUse.put(new ChunkPosition(x, z), M.ms()); - return c; + return c; + }); } public Hunk getR(int x, int z) { - return get(x, z).readOnly(); + return lock.withResult(x, z, () -> get(x, z).readOnly()); } public Hunk getRW(int x, int z) { - save.addIfMissing(new ChunkPosition(x, z)); - return get(x, z); + return lock.withResult(x, z, () -> { + save.addIfMissing(new ChunkPosition(x, z)); + return get(x, z); + }); } private String key(int x, int z) @@ -254,7 +289,7 @@ public class HunkRegionSlice return key + "." + x + "." + z; } - public int getLoadCount() + public int getLoadCount() { return loadedChunks.size(); } diff --git a/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxRegion.java b/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxRegion.java index b764be16f..760448e6c 100644 --- a/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxRegion.java +++ b/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxRegion.java @@ -4,6 +4,7 @@ import com.volmit.iris.scaffold.hunk.Hunk; import com.volmit.iris.scaffold.hunk.io.HunkIOAdapter; import com.volmit.iris.scaffold.hunk.io.HunkRegion; import com.volmit.iris.scaffold.hunk.io.HunkRegionSlice; +import com.volmit.iris.scaffold.parallel.GridLock; import com.volmit.iris.util.ByteArrayTag; import com.volmit.iris.util.CompoundTag; import com.volmit.iris.util.M; @@ -21,6 +22,7 @@ public class ParallaxRegion extends HunkRegion private HunkRegionSlice blockSlice; private HunkRegionSlice objectSlice; private HunkRegionSlice updateSlice; + private final GridLock lock; private long lastUse; private final int height; @@ -29,6 +31,7 @@ public class ParallaxRegion extends HunkRegion super(folder, x, z, compound); this.height = height; setupSlices(); + lock = new GridLock(32, 32); } public ParallaxRegion(int height, File folder, int x, int z) @@ -36,6 +39,7 @@ public class ParallaxRegion extends HunkRegion super(folder, x, z); this.height = height; setupSlices(); + lock = new GridLock(32, 32); } private void setupSlices() @@ -49,28 +53,30 @@ public class ParallaxRegion extends HunkRegion lastUse = M.ms(); } - public boolean hasBeenIdleLongerThan(long time) + public boolean hasBeenIdleLongerThan(long time) { return M.ms() - lastUse > time; } - public ParallaxChunkMeta getMetaR(int x, int z) + public ParallaxChunkMeta getMetaR(int x, int z) { - return getMetaHunkR().getOr(x, 0, z, new ParallaxChunkMeta()); + return lock.withResult(x, z, () -> getMetaHunkR().getOr(x, 0, z, new ParallaxChunkMeta())); } public ParallaxChunkMeta getMetaRW(int x, int z) { - lastUse = M.ms(); - dirtyMeta = true; - ParallaxChunkMeta p = getMetaHunkRW().get(x, 0, z); - if(p == null) - { - p = new ParallaxChunkMeta(); - getMetaHunkRW().set(x,0,z,p); - } + return lock.withResult(x, z, () -> { + lastUse = M.ms(); + dirtyMeta = true; + ParallaxChunkMeta p = getMetaHunkRW().get(x, 0, z); + if(p == null) + { + p = new ParallaxChunkMeta(); + getMetaHunkRW().set(x,0,z,p); + } - return p; + return p; + }); } private Hunk getMetaHunkR() @@ -89,7 +95,7 @@ public class ParallaxRegion extends HunkRegion return getMetaHunkR(); } - public Hunk loadMetaHunk() + private Hunk loadMetaHunk() { lastUse = M.ms(); if(meta == null) @@ -138,7 +144,7 @@ public class ParallaxRegion extends HunkRegion } } - public void save() throws IOException + public synchronized void save() throws IOException { blockSlice.save(); objectSlice.save(); @@ -147,7 +153,7 @@ public class ParallaxRegion extends HunkRegion super.save(); } - public int unload() + public int unload() { unloadMetaHunk(); return blockSlice.unloadAll()+ @@ -155,7 +161,7 @@ public class ParallaxRegion extends HunkRegion updateSlice.unloadAll(); } - public HunkRegionSlice getBlockSlice() { + public HunkRegionSlice getBlockSlice() { lastUse = M.ms(); return blockSlice; } @@ -165,18 +171,18 @@ public class ParallaxRegion extends HunkRegion return objectSlice; } - public HunkRegionSlice getUpdateSlice() { + public HunkRegionSlice getUpdateSlice() { lastUse = M.ms(); return updateSlice; } - public int cleanup(long c) { + public synchronized int cleanup(long c) { return blockSlice.cleanup(c) + objectSlice.cleanup(c) + updateSlice.cleanup(c); } - public int getChunkCount() { + public int getChunkCount() { return blockSlice.getLoadCount() + objectSlice.getLoadCount() + updateSlice.getLoadCount(); } } diff --git a/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxWorld.java b/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxWorld.java index 28c523974..d82f7f7a8 100644 --- a/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxWorld.java +++ b/src/main/java/com/volmit/iris/scaffold/parallax/ParallaxWorld.java @@ -26,12 +26,12 @@ public class ParallaxWorld implements ParallaxAccess folder.mkdirs(); } - public int getRegionCount() + public int getRegionCount() { return loadedRegions.size(); } - public int getChunkCount() + public int getChunkCount() { int m = 0; @@ -43,7 +43,7 @@ public class ParallaxWorld implements ParallaxAccess } } - catch(Throwable e) + catch(Throwable ignored) { } @@ -51,7 +51,7 @@ public class ParallaxWorld implements ParallaxAccess return m; } - public void close() + public void close() { for(ParallaxRegion i : loadedRegions.v()) { @@ -62,7 +62,7 @@ public class ParallaxWorld implements ParallaxAccess loadedRegions.clear(); } - public void save(ParallaxRegion region) + public void save(ParallaxRegion region) { try { @@ -75,12 +75,12 @@ public class ParallaxWorld implements ParallaxAccess } } - public boolean isLoaded(int x, int z) + public boolean isLoaded(int x, int z) { return loadedRegions.containsKey(key(x, z)); } - public void save(int x, int z) + public void save(int x, int z) { if(isLoaded(x, z)) { @@ -88,7 +88,7 @@ public class ParallaxWorld implements ParallaxAccess } } - public int unload(int x, int z) + public int unload(int x, int z) { long key = key(x, z); int v = 0; @@ -111,7 +111,7 @@ public class ParallaxWorld implements ParallaxAccess return v; } - public ParallaxRegion load(int x, int z) + public ParallaxRegion load(int x, int z) { if(isLoaded(x, z)) { @@ -124,7 +124,7 @@ public class ParallaxWorld implements ParallaxAccess return v; } - public ParallaxRegion getR(int x, int z) + public ParallaxRegion getR(int x, int z) { long key = key(x, z); @@ -138,7 +138,7 @@ public class ParallaxWorld implements ParallaxAccess return region; } - public ParallaxRegion getRW(int x, int z) + public ParallaxRegion getRW(int x, int z) { save.addIfMissing(key(x, z)); return getR(x, z); @@ -150,60 +150,60 @@ public class ParallaxWorld implements ParallaxAccess } @Override - public Hunk getBlocksR(int x, int z) + public Hunk getBlocksR(int x, int z) { return getR(x >> 5, z >> 5).getBlockSlice().getR(x & 31, z & 31); } @Override - public Hunk getBlocksRW(int x, int z) + public Hunk getBlocksRW(int x, int z) { return getRW(x >> 5, z >> 5).getBlockSlice().getRW(x & 31, z & 31); } @Override - public Hunk getObjectsR(int x, int z) + public Hunk getObjectsR(int x, int z) { return getR(x >> 5, z >> 5).getObjectSlice().getR(x & 31, z & 31); } @Override - public Hunk getObjectsRW(int x, int z) + public Hunk getObjectsRW(int x, int z) { return getRW(x >> 5, z >> 5).getObjectSlice().getRW(x & 31, z & 31); } @Override - public Hunk getUpdatesR(int x, int z) + public Hunk getUpdatesR(int x, int z) { return getR(x >> 5, z >> 5).getUpdateSlice().getR(x & 31, z & 31); } @Override - public Hunk getUpdatesRW(int x, int z) + public Hunk getUpdatesRW(int x, int z) { return getRW(x >> 5, z >> 5).getUpdateSlice().getRW(x & 31, z & 31); } @Override - public ParallaxChunkMeta getMetaR(int x, int z) + public ParallaxChunkMeta getMetaR(int x, int z) { return getR(x >> 5, z >> 5).getMetaR(x & 31, z & 31); } @Override - public ParallaxChunkMeta getMetaRW(int x, int z) + public ParallaxChunkMeta getMetaRW(int x, int z) { return getRW(x >> 5, z >> 5).getMetaRW(x & 31, z & 31); } - public void cleanup() + public void cleanup() { cleanup(IrisSettings.get().getParallaxRegionEvictionMS(), IrisSettings.get().getParallax().getParallaxChunkEvictionMS()); } @Override - public void cleanup(long r, long c) { + public void cleanup(long r, long c) { J.a(() -> { try { @@ -233,12 +233,12 @@ public class ParallaxWorld implements ParallaxAccess } @Override - public void saveAll() { + public void saveAll() { J.a(this::saveAllNOW); } @Override - public void saveAllNOW() { + public void saveAllNOW() { for(ParallaxRegion i : loadedRegions.v()) { if(save.contains(key(i.getX(), i.getZ()))) diff --git a/src/main/java/com/volmit/iris/scaffold/parallel/GridLock.java b/src/main/java/com/volmit/iris/scaffold/parallel/GridLock.java index e7c47288f..4163861dd 100644 --- a/src/main/java/com/volmit/iris/scaffold/parallel/GridLock.java +++ b/src/main/java/com/volmit/iris/scaffold/parallel/GridLock.java @@ -1,2 +1,89 @@ -package com.volmit.iris.scaffold.parallel;public class GridLock { +package com.volmit.iris.scaffold.parallel; + +import com.volmit.iris.scaffold.hunk.Hunk; +import com.volmit.iris.util.IORunnable; +import com.volmit.iris.util.NastyRunnable; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Supplier; + +public class GridLock +{ + private Hunk locks; + + public GridLock(int x, int z) + { + this.locks = Hunk.newAtomicHunk(x, 1, z); + locks.iterateSync((a,b,c) -> locks.set(a,b,c,new ReentrantLock())); + } + + public void with(int x, int z, Runnable r) + { + lock(x, z); + r.run(); + unlock(x, z); + } + + public void withNasty(int x, int z, NastyRunnable r) throws Throwable { + lock(x, z); + r.run(); + unlock(x, z); + } + + public void withIO(int x, int z, IORunnable r) throws IOException { + lock(x, z); + r.run(); + unlock(x, z); + } + + public T withResult(int x, int z, Supplier r) + { + lock(x, z); + T t = r.get(); + unlock(x, z); + return t; + } + + public void withAll(Runnable r) + { + locks.iterateSync((a,b,c,d) -> d.lock()); + r.run(); + locks.iterateSync((a,b,c,d) -> d.unlock()); + } + + public T withAllResult(Supplier r) + { + locks.iterateSync((a,b,c,d) -> d.lock()); + T t = r.get(); + locks.iterateSync((a,b,c,d) -> d.unlock()); + + return t; + } + + public boolean tryLock(int x, int z) + { + return locks.get(x,0,z).tryLock(); + } + + public boolean tryLock(int x, int z, long timeout) + { + try { + return locks.get(x,0,z).tryLock(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException ignored) { + } + + return false; + } + + public void lock(int x, int z) + { + locks.get(x,0,z).lock(); + } + + public void unlock(int x, int z) + { + locks.get(x,0,z).unlock(); + } } diff --git a/src/main/java/com/volmit/iris/util/IORunnable.java b/src/main/java/com/volmit/iris/util/IORunnable.java index 815b20448..010fd7366 100644 --- a/src/main/java/com/volmit/iris/util/IORunnable.java +++ b/src/main/java/com/volmit/iris/util/IORunnable.java @@ -1,6 +1,8 @@ package com.volmit.iris.util; -public interface NastyRunnable +import java.io.IOException; + +public interface IORunnable { - public void run() throws Throwable; + public void run() throws IOException; }