geforkt von Mirrors/FastAsyncWorldEdit
document some methods
Dieser Commit ist enthalten in:
Ursprung
57b5be84f4
Commit
6692a2eb92
@ -38,7 +38,7 @@ public class BukkitChunkHolder extends ChunkHolder<Boolean, BukkitQueue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(final Filter filter) {
|
public void set(final Filter filter) {
|
||||||
// for each block
|
// for each block
|
||||||
// filter.applyBlock(block)
|
// filter.applyBlock(block)
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
@ -21,7 +21,7 @@ public class BukkitFullChunk extends ChunkHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(Filter filter) {
|
public void set(Filter filter) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@ package com.boydti.fawe.beta;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A filter is an interface used for setting blocks
|
||||||
|
*/
|
||||||
public interface Filter {
|
public interface Filter {
|
||||||
/**
|
/**
|
||||||
* Check whether a chunk should be read
|
* Check whether a chunk should be read
|
||||||
@ -47,4 +50,13 @@ public interface Filter {
|
|||||||
*/
|
*/
|
||||||
default void finishChunk(final IChunk chunk) {
|
default void finishChunk(final IChunk chunk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fork this for use by another thread
|
||||||
|
* - Typically filters are simple and don't need to create another copy to be thread safe here
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
default Filter fork() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.boydti.fawe.beta;
|
package com.boydti.fawe.beta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared interface for IGetBlocks and ISetBlocks
|
||||||
|
*/
|
||||||
public interface IBlocks {
|
public interface IBlocks {
|
||||||
|
|
||||||
}
|
}
|
@ -5,30 +5,59 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
|||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
public interface IChunk<T, V extends IQueueExtent> {
|
/**
|
||||||
/* set */
|
* Represents a chunk in the queue {@link IQueueExtent}
|
||||||
boolean setBiome(int x, int y, int z, BiomeType biome);
|
* Used for getting and setting blocks / biomes / entities
|
||||||
|
* @param <T> The result type (typically returns true when the chunk is applied)
|
||||||
boolean setBlock(int x, int y, int z, BlockStateHolder block);
|
* @param <V> The IQueue class
|
||||||
|
*/
|
||||||
/* get */
|
public interface IChunk<T, V extends IQueueExtent> extends Trimable {
|
||||||
BiomeType getBiome(int x, int z);
|
/**
|
||||||
|
* Initialize at the location
|
||||||
BlockState getBlock(int x, int y, int z);
|
* @param extent
|
||||||
|
* @param X
|
||||||
BaseBlock getFullBlock(int x, int y, int z);
|
* @param Z
|
||||||
|
*/
|
||||||
void init(V extent, int X, int Z);
|
void init(V extent, int X, int Z);
|
||||||
|
|
||||||
T apply();
|
|
||||||
|
|
||||||
int getX();
|
int getX();
|
||||||
|
|
||||||
int getZ();
|
int getZ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the chunk is a delegate, returns it's paren'ts root
|
||||||
|
* @return root IChunk
|
||||||
|
*/
|
||||||
default IChunk getRoot() {
|
default IChunk getRoot() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void filter(Filter filter);
|
/**
|
||||||
|
* @return true if no changes are queued for this chunk
|
||||||
|
*/
|
||||||
|
boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the queued changes to the world
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
T apply();
|
||||||
|
|
||||||
|
/* set - queues a change */
|
||||||
|
boolean setBiome(int x, int y, int z, BiomeType biome);
|
||||||
|
|
||||||
|
boolean setBlock(int x, int y, int z, BlockStateHolder block);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set using the filter
|
||||||
|
* @param filter
|
||||||
|
*/
|
||||||
|
void set(Filter filter);
|
||||||
|
|
||||||
|
/* get - from the world */
|
||||||
|
BiomeType getBiome(int x, int z);
|
||||||
|
|
||||||
|
BlockState getBlock(int x, int y, int z);
|
||||||
|
|
||||||
|
BaseBlock getFullBlock(int x, int y, int z);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
package com.boydti.fawe.beta;
|
package com.boydti.fawe.beta;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate for IChunk
|
||||||
|
* @param <T> The result type (typically returns true when the chunk is applied)
|
||||||
|
* @param <V> The IQueue class
|
||||||
|
* @param <U> parent class
|
||||||
|
*/
|
||||||
public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V>> extends IChunk<T, V> {
|
public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V>> extends IChunk<T, V> {
|
||||||
U getParent();
|
U getParent();
|
||||||
|
|
||||||
@ -57,11 +62,26 @@ public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V
|
|||||||
return getParent().getZ();
|
return getParent().getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean trim(boolean aggressive) {
|
||||||
|
return getParent().trim(aggressive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this chunk to the world
|
||||||
|
* @return result T (typically a boolean)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
default T apply() {
|
default T apply() {
|
||||||
return getParent().apply();
|
return getParent().apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isEmpty() {
|
||||||
|
return getParent().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
default <T extends IChunk> T findParent(final Class<T> clazz) {
|
default <T extends IChunk> T findParent(final Class<T> clazz) {
|
||||||
IChunk root = getParent();
|
IChunk root = getParent();
|
||||||
if (clazz.isAssignableFrom(root.getClass())) return (T) root;
|
if (clazz.isAssignableFrom(root.getClass())) return (T) root;
|
||||||
@ -73,7 +93,7 @@ public interface IDelegateChunk<T, V extends IQueueExtent, U extends IChunk<T, V
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void filter(Filter filter) {
|
default void set(Filter filter) {
|
||||||
getParent().filter(filter);
|
getParent().set(filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@ import com.boydti.fawe.beta.implementation.WorldChunkCache;
|
|||||||
|
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate for IQueueExtent
|
||||||
|
*/
|
||||||
public interface IDelegateQueueExtent extends IQueueExtent {
|
public interface IDelegateQueueExtent extends IQueueExtent {
|
||||||
IQueueExtent getParent();
|
IQueueExtent getParent();
|
||||||
|
|
||||||
|
@ -4,12 +4,16 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
|
||||||
public interface IGetBlocks extends IBlocks {
|
/**
|
||||||
|
* Interface for getting blocks
|
||||||
|
*/
|
||||||
|
public interface IGetBlocks extends IBlocks, Trimable {
|
||||||
BaseBlock getFullBlock(int x, int y, int z);
|
BaseBlock getFullBlock(int x, int y, int z);
|
||||||
|
|
||||||
BiomeType getBiome(int x, int z);
|
BiomeType getBiome(int x, int z);
|
||||||
|
|
||||||
BlockState getBlock(int x, int y, int z);
|
BlockState getBlock(int x, int y, int z);
|
||||||
|
|
||||||
void trim();
|
@Override
|
||||||
|
boolean trim(boolean aggressive);
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,27 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
import java.io.Flushable;
|
import java.io.Flushable;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: implement Extent (need to refactor Extent first)
|
||||||
|
* Interface for a queue based extent which uses chunks
|
||||||
|
*/
|
||||||
public interface IQueueExtent extends Flushable, Trimable {
|
public interface IQueueExtent extends Flushable, Trimable {
|
||||||
void init(WorldChunkCache world);
|
void init(WorldChunkCache world);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IChunk at a position (and cache it if it's not already)
|
||||||
|
* @param X
|
||||||
|
* @param Z
|
||||||
|
* @return IChunk
|
||||||
|
*/
|
||||||
IChunk getCachedChunk(int X, int Z);
|
IChunk getCachedChunk(int X, int Z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit the chunk so that it's changes are applied to the world
|
||||||
|
* @param chunk
|
||||||
|
* @param <T> result type
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
<T> Future<T> submit(IChunk<T, ?> chunk);
|
<T> Future<T> submit(IChunk<T, ?> chunk);
|
||||||
|
|
||||||
default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder state) {
|
default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder state) {
|
||||||
@ -36,14 +52,16 @@ public interface IQueueExtent extends Flushable, Trimable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the IChunk
|
* Create a new root IChunk object<br>
|
||||||
|
* - Full chunks will be reused, so a more optimized chunk can be returned in that case<br>
|
||||||
|
* - Don't wrap the chunk, that should be done in {@link #wrap(IChunk)}
|
||||||
* @param full
|
* @param full
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
IChunk create(boolean full);
|
IChunk create(boolean full);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap the chunk object (i.e. for region restrictions etc.)
|
* Wrap the chunk object (i.e. for region restrictions / limits etc.)
|
||||||
* @param root
|
* @param root
|
||||||
* @return wrapped chunk
|
* @return wrapped chunk
|
||||||
*/
|
*/
|
||||||
@ -51,6 +69,10 @@ public interface IQueueExtent extends Flushable, Trimable {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all changes to the world
|
||||||
|
* - Best to call this async so it doesn't hang the server
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
void flush();
|
void flush();
|
||||||
}
|
}
|
@ -3,8 +3,13 @@ package com.boydti.fawe.beta;
|
|||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for setting blocks
|
||||||
|
*/
|
||||||
public interface ISetBlocks extends IBlocks {
|
public interface ISetBlocks extends IBlocks {
|
||||||
boolean setBiome(int x, int y, int z, BiomeType biome);
|
boolean setBiome(int x, int y, int z, BiomeType biome);
|
||||||
|
|
||||||
boolean setBlock(int x, int y, int z, BlockStateHolder holder);
|
boolean setBlock(int x, int y, int z, BlockStateHolder holder);
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
package com.boydti.fawe.beta;
|
package com.boydti.fawe.beta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for objects that can be trimmed (memory related)<br>
|
||||||
|
* - Trimming will reduce it's memory footprint
|
||||||
|
*/
|
||||||
public interface Trimable {
|
public interface Trimable {
|
||||||
|
/**
|
||||||
|
* Trim the object, reducing it's memory footprint
|
||||||
|
* @param aggressive if trimming should be aggressive e.g. Not return early when the first element cannot be trimmed
|
||||||
|
* @return if this object is empty at the end of the trim, and can therefore be deleted
|
||||||
|
*/
|
||||||
boolean trim(boolean aggressive);
|
boolean trim(boolean aggressive);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import com.boydti.fawe.beta.Filter;
|
|||||||
import com.boydti.fawe.beta.IQueueExtent;
|
import com.boydti.fawe.beta.IQueueExtent;
|
||||||
import com.boydti.fawe.beta.Trimable;
|
import com.boydti.fawe.beta.Trimable;
|
||||||
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
import com.boydti.fawe.object.collection.IterableThreadLocal;
|
||||||
|
import com.boydti.fawe.wrappers.WorldWrapper;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
@ -12,8 +13,12 @@ import java.util.HashMap;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which handles all the queues {@link IQueueExtent}
|
||||||
|
*/
|
||||||
public abstract class QueueHandler implements Trimable {
|
public abstract class QueueHandler implements Trimable {
|
||||||
private Map<World, WeakReference<WorldChunkCache>> chunkCache = new HashMap<>();
|
private Map<World, WeakReference<WorldChunkCache>> chunkCache = new HashMap<>();
|
||||||
|
|
||||||
private IterableThreadLocal<IQueueExtent> pool = new IterableThreadLocal<IQueueExtent>() {
|
private IterableThreadLocal<IQueueExtent> pool = new IterableThreadLocal<IQueueExtent>() {
|
||||||
@Override
|
@Override
|
||||||
public IQueueExtent init() {
|
public IQueueExtent init() {
|
||||||
@ -21,7 +26,14 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public WorldChunkCache getOrCreate(final World world) {
|
/**
|
||||||
|
* Get or create the WorldChunkCache for a world
|
||||||
|
* @param world
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public WorldChunkCache getOrCreate(World world) {
|
||||||
|
world = WorldWrapper.unwrap(world);
|
||||||
|
|
||||||
synchronized (chunkCache) {
|
synchronized (chunkCache) {
|
||||||
final WeakReference<WorldChunkCache> ref = chunkCache.get(world);
|
final WeakReference<WorldChunkCache> ref = chunkCache.get(world);
|
||||||
if (ref != null) {
|
if (ref != null) {
|
||||||
@ -38,6 +50,7 @@ public abstract class QueueHandler implements Trimable {
|
|||||||
|
|
||||||
public abstract IQueueExtent create();
|
public abstract IQueueExtent create();
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean trim(final boolean aggressive) {
|
public boolean trim(final boolean aggressive) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
synchronized (chunkCache) {
|
synchronized (chunkCache) {
|
||||||
|
@ -6,6 +6,7 @@ import com.boydti.fawe.beta.implementation.holder.ReferenceChunk;
|
|||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.MemUtil;
|
import com.boydti.fawe.util.MemUtil;
|
||||||
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
|
|
||||||
@ -16,20 +17,37 @@ import java.util.concurrent.ForkJoinTask;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single threaded implementation for IQueueExtent (still abstract)
|
||||||
|
* - Does not implement creation of chunks (that has to implemented by the platform e.g. Bukkit)
|
||||||
|
*
|
||||||
|
* This queue is reusable {@link #init(WorldChunkCache)}
|
||||||
|
*/
|
||||||
public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
||||||
private WorldChunkCache cache;
|
private WorldChunkCache cache;
|
||||||
private Thread currentThread;
|
private Thread currentThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safety check to ensure that the thread being used matches the one being initialized on
|
||||||
|
* - Can be removed later
|
||||||
|
*/
|
||||||
private void checkThread() {
|
private void checkThread() {
|
||||||
if (Thread.currentThread() != currentThread && currentThread != null) {
|
if (Thread.currentThread() != currentThread && currentThread != null) {
|
||||||
throw new UnsupportedOperationException("This class must be used from a single thread. Use multiple queues for concurrent operations");
|
throw new UnsupportedOperationException("This class must be used from a single thread. Use multiple queues for concurrent operations");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link WorldChunkCache}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public WorldChunkCache getCache() {
|
public WorldChunkCache getCache() {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the queue
|
||||||
|
*/
|
||||||
protected synchronized void reset() {
|
protected synchronized void reset() {
|
||||||
checkThread();
|
checkThread();
|
||||||
cache = null;
|
cache = null;
|
||||||
@ -37,7 +55,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
for (IChunk chunk : chunks.values()) {
|
for (IChunk chunk : chunks.values()) {
|
||||||
chunk = chunk.getRoot();
|
chunk = chunk.getRoot();
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
chunkPool.add(chunk);
|
CHUNK_POOL.add(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunks.clear();
|
chunks.clear();
|
||||||
@ -47,6 +65,10 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
currentThread = null;
|
currentThread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the queue
|
||||||
|
* @param cache
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(final WorldChunkCache cache) {
|
public synchronized void init(final WorldChunkCache cache) {
|
||||||
if (cache != null) {
|
if (cache != null) {
|
||||||
@ -57,24 +79,32 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last access pointers
|
||||||
private IChunk lastChunk;
|
private IChunk lastChunk;
|
||||||
private long lastPair = Long.MAX_VALUE;
|
private long lastPair = Long.MAX_VALUE;
|
||||||
|
// Chunks currently being queued / worked on
|
||||||
private final Long2ObjectLinkedOpenHashMap<IChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
private final Long2ObjectLinkedOpenHashMap<IChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
||||||
private final ConcurrentLinkedQueue<IChunk> chunkPool = new ConcurrentLinkedQueue<>();
|
// Pool discarded chunks for reuse (can safely be cleared by another thread)
|
||||||
|
private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> ForkJoinTask<T> submit(final IChunk<T, ?> tmp) {
|
public <T> ForkJoinTask<T> submit(final IChunk<T, ?> chunk) {
|
||||||
|
if (chunk.isEmpty()) {
|
||||||
|
CHUNK_POOL.add(chunk);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// TODO use SetQueue to run in parallel
|
||||||
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
|
||||||
return pool.submit(new Callable<T>() {
|
return pool.submit(new Callable<T>() {
|
||||||
@Override
|
@Override
|
||||||
public T call() {
|
public T call() {
|
||||||
IChunk<T, ?> chunk = tmp;
|
IChunk<T, ?> tmp = chunk;
|
||||||
|
|
||||||
T result = chunk.apply();
|
T result = tmp.apply();
|
||||||
|
|
||||||
chunk = chunk.getRoot();
|
tmp = tmp.getRoot();
|
||||||
if (chunk != null) {
|
if (tmp != null) {
|
||||||
chunkPool.add(chunk);
|
CHUNK_POOL.add(tmp);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -83,7 +113,8 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean trim(boolean aggressive) {
|
public synchronized boolean trim(boolean aggressive) {
|
||||||
chunkPool.clear();
|
// TODO trim individial chunk sections
|
||||||
|
CHUNK_POOL.clear();
|
||||||
if (Thread.currentThread() == currentThread) {
|
if (Thread.currentThread() == currentThread) {
|
||||||
lastChunk = null;
|
lastChunk = null;
|
||||||
lastPair = Long.MAX_VALUE;
|
lastPair = Long.MAX_VALUE;
|
||||||
@ -94,13 +125,21 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IChunk pool(final int X, final int Z) {
|
/**
|
||||||
IChunk next = chunkPool.poll();
|
* Get a new IChunk from either the pool, or create a new one<br>
|
||||||
|
* + Initialize it at the coordinates
|
||||||
|
* @param X
|
||||||
|
* @param Z
|
||||||
|
* @return IChunk
|
||||||
|
*/
|
||||||
|
private IChunk poolOrCreate(final int X, final int Z) {
|
||||||
|
IChunk next = CHUNK_POOL.poll();
|
||||||
if (next == null) next = create(false);
|
if (next == null) next = create(false);
|
||||||
next.init(this, X, Z);
|
next.init(this, X, Z);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final IChunk getCachedChunk(final int X, final int Z) {
|
public final IChunk getCachedChunk(final int X, final int Z) {
|
||||||
final long pair = MathMan.pairInt(X, Z);
|
final long pair = MathMan.pairInt(X, Z);
|
||||||
if (pair == lastPair) {
|
if (pair == lastPair) {
|
||||||
@ -125,7 +164,7 @@ public abstract class SingleThreadQueueExtent implements IQueueExtent {
|
|||||||
submit(chunk);
|
submit(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk = pool(X, Z);
|
chunk = poolOrCreate(X, Z);
|
||||||
chunk = wrap(chunk);
|
chunk = wrap(chunk);
|
||||||
|
|
||||||
chunks.put(pair, chunk);
|
chunks.put(pair, chunk);
|
||||||
|
@ -10,6 +10,10 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IGetBlocks may be cached by the WorldChunkCache so that it can be used between multiple IQueueExtents
|
||||||
|
* - avoids conversion between palette and raw data on every block get
|
||||||
|
*/
|
||||||
public class WorldChunkCache implements Trimable {
|
public class WorldChunkCache implements Trimable {
|
||||||
protected final Long2ObjectLinkedOpenHashMap<WeakReference<IGetBlocks>> getCache;
|
protected final Long2ObjectLinkedOpenHashMap<WeakReference<IGetBlocks>> getCache;
|
||||||
private final World world;
|
private final World world;
|
||||||
@ -27,6 +31,12 @@ public class WorldChunkCache implements Trimable {
|
|||||||
return getCache.size();
|
return getCache.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or create the IGetBlocks
|
||||||
|
* @param index chunk index {@link com.boydti.fawe.util.MathMan#pairInt(int, int)}
|
||||||
|
* @param provider used to create if it isn't already cached
|
||||||
|
* @return cached IGetBlocks
|
||||||
|
*/
|
||||||
public synchronized IGetBlocks get(final long index, final Supplier<IGetBlocks> provider) {
|
public synchronized IGetBlocks get(final long index, final Supplier<IGetBlocks> provider) {
|
||||||
final WeakReference<IGetBlocks> ref = getCache.get(index);
|
final WeakReference<IGetBlocks> ref = getCache.get(index);
|
||||||
if (ref != null) {
|
if (ref != null) {
|
||||||
@ -52,7 +62,7 @@ public class WorldChunkCache implements Trimable {
|
|||||||
result = false;
|
result = false;
|
||||||
if (!aggressive) return result;
|
if (!aggressive) return result;
|
||||||
synchronized (igb) {
|
synchronized (igb) {
|
||||||
igb.trim();
|
igb.trim(aggressive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract IChunk class that implements basic get/set blocks
|
||||||
|
*/
|
||||||
public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implements IChunk<T, V>, Supplier<IGetBlocks> {
|
public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implements IChunk<T, V>, Supplier<IGetBlocks> {
|
||||||
private IGetBlocks get;
|
private IGetBlocks get;
|
||||||
private ISetBlocks set;
|
private ISetBlocks set;
|
||||||
@ -30,6 +33,11 @@ public abstract class ChunkHolder<T, V extends SingleThreadQueueExtent> implemen
|
|||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return set == null || set.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public final IGetBlocks cachedGet() {
|
public final IGetBlocks cachedGet() {
|
||||||
if (get == null) get = newGet();
|
if (get == null) get = newGet();
|
||||||
return get;
|
return get;
|
||||||
|
@ -3,6 +3,10 @@ package com.boydti.fawe.beta.implementation.holder;
|
|||||||
import com.boydti.fawe.beta.IChunk;
|
import com.boydti.fawe.beta.IChunk;
|
||||||
import com.boydti.fawe.beta.IDelegateChunk;
|
import com.boydti.fawe.beta.IDelegateChunk;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of IDelegateChunk
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
public class DelegateChunk<T extends IChunk> implements IDelegateChunk {
|
public class DelegateChunk<T extends IChunk> implements IDelegateChunk {
|
||||||
private T parent;
|
private T parent;
|
||||||
|
|
||||||
|
@ -6,6 +6,11 @@ import com.boydti.fawe.beta.IQueueExtent;
|
|||||||
|
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An IChunk may be wrapped by a ReferenceChunk if there is low memory<br>
|
||||||
|
* A reference chunk stores a reference (for garbage collection purposes)<br>
|
||||||
|
* - If it is garbage collected, the {@link FinalizedChunk} logic is run
|
||||||
|
*/
|
||||||
public abstract class ReferenceChunk implements IDelegateChunk {
|
public abstract class ReferenceChunk implements IDelegateChunk {
|
||||||
private final Reference<FinalizedChunk> ref;
|
private final Reference<FinalizedChunk> ref;
|
||||||
|
|
||||||
|
@ -6,9 +6,12 @@ import com.boydti.fawe.beta.IQueueExtent;
|
|||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Soft reference implementation of {@link ReferenceChunk}
|
||||||
|
*/
|
||||||
public class SoftChunk extends ReferenceChunk {
|
public class SoftChunk extends ReferenceChunk {
|
||||||
|
|
||||||
public SoftChunk(final IChunk parent, IQueueExtent queueExtent) {
|
public SoftChunk(final IChunk parent, final IQueueExtent queueExtent) {
|
||||||
super(parent, queueExtent);
|
super(parent, queueExtent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package com.boydti.fawe.beta.implementation.holder;
|
package com.boydti.fawe.beta.implementation.holder;
|
||||||
|
|
||||||
import com.boydti.fawe.beta.IChunk;
|
import com.boydti.fawe.beta.IChunk;
|
||||||
|
import com.boydti.fawe.beta.IQueueExtent;
|
||||||
|
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Weak reference implementation of {@link ReferenceChunk}
|
||||||
|
*/
|
||||||
public class WeakChunk extends ReferenceChunk {
|
public class WeakChunk extends ReferenceChunk {
|
||||||
public WeakChunk(final IChunk parent) {
|
public WeakChunk(final IChunk parent, final IQueueExtent queueExtent) {
|
||||||
super(parent);
|
super(parent, queueExtent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren