2019-11-02 11:13:42 +00:00
|
|
|
package com.boydti.fawe.beta.implementation.queue;
|
2019-04-28 15:44:59 +00:00
|
|
|
|
2019-04-30 16:19:10 +00:00
|
|
|
import com.boydti.fawe.Fawe;
|
2019-04-28 15:44:59 +00:00
|
|
|
import com.boydti.fawe.beta.IChunk;
|
2019-11-11 21:02:28 +00:00
|
|
|
import com.boydti.fawe.beta.IChunkCache;
|
2019-07-16 19:10:39 +00:00
|
|
|
import com.boydti.fawe.beta.IChunkGet;
|
2019-08-18 01:09:09 +00:00
|
|
|
import com.boydti.fawe.beta.IChunkSet;
|
2019-11-11 21:02:28 +00:00
|
|
|
import com.boydti.fawe.beta.IQueueChunk;
|
2019-04-28 15:44:59 +00:00
|
|
|
import com.boydti.fawe.beta.IQueueExtent;
|
2019-08-18 01:09:09 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
|
2019-11-02 11:13:42 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.chunk.ChunkHolder;
|
2019-11-11 21:02:28 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.chunk.NullChunk;
|
|
|
|
import com.boydti.fawe.beta.implementation.filter.block.CharFilterBlock;
|
|
|
|
import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock;
|
2019-11-02 11:13:42 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.processors.EmptyBatchProcessor;
|
2019-11-06 09:29:20 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.processors.ExtentBatchProcessorHolder;
|
2021-01-11 19:29:16 +00:00
|
|
|
import com.boydti.fawe.beta.implementation.processors.ProcessorScope;
|
2019-04-28 15:44:59 +00:00
|
|
|
import com.boydti.fawe.config.Settings;
|
2021-01-13 20:30:22 +00:00
|
|
|
import com.boydti.fawe.object.exception.FaweException;
|
2019-05-02 14:45:03 +00:00
|
|
|
import com.boydti.fawe.util.MathMan;
|
2019-04-28 15:44:59 +00:00
|
|
|
import com.boydti.fawe.util.MemUtil;
|
2019-05-01 15:45:18 +00:00
|
|
|
import com.google.common.util.concurrent.Futures;
|
2019-08-18 01:09:09 +00:00
|
|
|
import com.sk89q.worldedit.extent.Extent;
|
2021-03-29 13:29:16 +00:00
|
|
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
2019-04-28 15:44:59 +00:00
|
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
2021-03-29 13:29:16 +00:00
|
|
|
import org.apache.logging.log4j.Logger;
|
2020-07-14 02:50:59 +00:00
|
|
|
|
2019-04-28 15:44:59 +00:00
|
|
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
2019-04-30 16:19:10 +00:00
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
import java.util.concurrent.Future;
|
2020-09-25 14:00:42 +00:00
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
2019-04-28 15:44:59 +00:00
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
/**
|
2019-08-06 15:29:09 +00:00
|
|
|
* Single threaded implementation for IQueueExtent (still abstract) - Does not implement creation of
|
2019-11-11 21:02:28 +00:00
|
|
|
* chunks (that has to implemented by the platform e.g., Bukkit)
|
2019-08-06 15:29:09 +00:00
|
|
|
* <p>
|
2019-11-11 21:22:03 +00:00
|
|
|
* This queue is reusable {@link #init(Extent, IChunkCache, IChunkCache)} }
|
2019-04-28 17:36:23 +00:00
|
|
|
*/
|
2019-11-07 10:28:17 +00:00
|
|
|
public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent<IQueueChunk> {
|
2019-08-06 15:29:09 +00:00
|
|
|
|
2021-03-29 13:29:16 +00:00
|
|
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
2021-01-13 20:30:22 +00:00
|
|
|
|
2020-01-03 17:02:18 +00:00
|
|
|
// Pool discarded chunks for reuse (can safely be cleared by another thread)
|
|
|
|
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
2019-08-06 15:29:09 +00:00
|
|
|
// Chunks currently being queued / worked on
|
2019-11-07 10:28:17 +00:00
|
|
|
private final Long2ObjectLinkedOpenHashMap<IQueueChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
2019-08-18 01:09:09 +00:00
|
|
|
|
|
|
|
private IChunkCache<IChunkGet> cacheGet;
|
|
|
|
private IChunkCache<IChunkSet> cacheSet;
|
|
|
|
private boolean initialized;
|
|
|
|
|
2019-04-28 15:44:59 +00:00
|
|
|
private Thread currentThread;
|
2019-05-01 15:45:18 +00:00
|
|
|
private ConcurrentLinkedQueue<Future> submissions = new ConcurrentLinkedQueue<>();
|
2019-08-06 15:29:09 +00:00
|
|
|
// Last access pointers
|
2019-11-07 10:28:17 +00:00
|
|
|
private IQueueChunk lastChunk;
|
2019-08-06 15:29:09 +00:00
|
|
|
private long lastPair = Long.MAX_VALUE;
|
2019-04-28 15:44:59 +00:00
|
|
|
|
2019-08-18 01:09:09 +00:00
|
|
|
private boolean enabledQueue = true;
|
|
|
|
|
2020-05-11 14:36:52 +00:00
|
|
|
private boolean fastmode = false;
|
|
|
|
|
2020-09-25 14:00:42 +00:00
|
|
|
private final ReentrantLock getChunkLock = new ReentrantLock();
|
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
/**
|
2019-08-06 15:29:09 +00:00
|
|
|
* Safety check to ensure that the thread being used matches the one being initialized on. - Can
|
|
|
|
* be removed later
|
2019-04-28 17:36:23 +00:00
|
|
|
*/
|
2019-04-28 15:44:59 +00:00
|
|
|
private void checkThread() {
|
|
|
|
if (Thread.currentThread() != currentThread && currentThread != null) {
|
2019-08-06 15:29:09 +00:00
|
|
|
throw new UnsupportedOperationException(
|
|
|
|
"This class must be used from a single thread. Use multiple queues for concurrent operations");
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-30 16:19:10 +00:00
|
|
|
@Override
|
2019-08-18 01:09:09 +00:00
|
|
|
public void enableQueue() {
|
|
|
|
enabledQueue = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void disableQueue() {
|
|
|
|
enabledQueue = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-02-14 19:29:08 +00:00
|
|
|
public IChunkGet getCachedGet(int chunkX, int chunkZ) {
|
|
|
|
return cacheGet.get(chunkX, chunkZ);
|
2019-08-18 01:09:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-02-14 19:29:08 +00:00
|
|
|
public IChunkSet getCachedSet(int chunkX, int chunkZ) {
|
|
|
|
return cacheSet.get(chunkX, chunkZ);
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 14:36:52 +00:00
|
|
|
@Override
|
|
|
|
public void setFastMode(boolean fastmode) {
|
|
|
|
this.fastmode = fastmode;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isFastMode() {
|
|
|
|
return fastmode;
|
|
|
|
}
|
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
/**
|
2019-07-25 19:09:12 +00:00
|
|
|
* Resets the queue.
|
2019-04-28 17:36:23 +00:00
|
|
|
*/
|
2019-04-28 15:44:59 +00:00
|
|
|
protected synchronized void reset() {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (!this.initialized) {
|
|
|
|
return;
|
|
|
|
}
|
2019-10-23 04:23:52 +00:00
|
|
|
if (!this.chunks.isEmpty()) {
|
|
|
|
for (IChunk chunk : this.chunks.values()) {
|
2019-08-18 01:09:09 +00:00
|
|
|
chunk.recycle();
|
|
|
|
}
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.lock();
|
2019-10-23 04:23:52 +00:00
|
|
|
this.chunks.clear();
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.unlock();
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
2019-10-23 04:23:52 +00:00
|
|
|
this.enabledQueue = true;
|
|
|
|
this.lastChunk = null;
|
|
|
|
this.lastPair = Long.MAX_VALUE;
|
|
|
|
this.currentThread = null;
|
|
|
|
this.initialized = false;
|
2020-09-17 20:31:55 +00:00
|
|
|
this.setProcessor(EmptyBatchProcessor.getInstance());
|
2020-09-28 10:13:02 +00:00
|
|
|
this.setPostProcessor(EmptyBatchProcessor.getInstance());
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
/**
|
|
|
|
* Initialize the queue
|
2019-08-06 15:29:09 +00:00
|
|
|
*
|
2019-04-28 17:36:23 +00:00
|
|
|
*/
|
2019-04-28 15:44:59 +00:00
|
|
|
@Override
|
2019-08-18 01:09:09 +00:00
|
|
|
public synchronized void init(Extent extent, IChunkCache<IChunkGet> get, IChunkCache<IChunkSet> set) {
|
|
|
|
reset();
|
2019-04-28 15:44:59 +00:00
|
|
|
currentThread = Thread.currentThread();
|
2019-08-18 01:09:09 +00:00
|
|
|
if (get == null) {
|
|
|
|
get = (x, z) -> { throw new UnsupportedOperationException(); };
|
|
|
|
}
|
|
|
|
if (set == null) {
|
|
|
|
set = (x, z) -> CharSetBlocks.newInstance();
|
|
|
|
}
|
|
|
|
this.cacheGet = get;
|
|
|
|
this.cacheSet = set;
|
2020-09-17 20:31:55 +00:00
|
|
|
this.setProcessor(EmptyBatchProcessor.getInstance());
|
2020-09-28 10:13:02 +00:00
|
|
|
this.setPostProcessor(EmptyBatchProcessor.getInstance());
|
2019-08-18 01:09:09 +00:00
|
|
|
initialized = true;
|
2019-05-01 18:19:15 +00:00
|
|
|
}
|
|
|
|
|
2019-07-22 09:05:14 +00:00
|
|
|
@Override
|
|
|
|
public int size() {
|
|
|
|
return chunks.size() + submissions.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isEmpty() {
|
|
|
|
return chunks.isEmpty() && submissions.isEmpty();
|
|
|
|
}
|
|
|
|
|
2019-04-28 15:44:59 +00:00
|
|
|
@Override
|
2019-11-07 10:28:17 +00:00
|
|
|
public <V extends Future<V>> V submit(IQueueChunk chunk) {
|
2019-05-02 14:45:03 +00:00
|
|
|
if (lastChunk == chunk) {
|
|
|
|
lastPair = Long.MAX_VALUE;
|
|
|
|
lastChunk = null;
|
|
|
|
}
|
|
|
|
final long index = MathMan.pairInt(chunk.getX(), chunk.getZ());
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.lock();
|
2019-05-02 14:45:03 +00:00
|
|
|
chunks.remove(index, chunk);
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.unlock();
|
2019-11-18 14:49:52 +00:00
|
|
|
V future = submitUnchecked(chunk);
|
|
|
|
submissions.add(future);
|
|
|
|
return future;
|
2019-05-02 14:45:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Submit without first checking that it has been removed from the chunk map
|
2019-08-06 15:29:09 +00:00
|
|
|
*
|
2019-05-02 14:45:03 +00:00
|
|
|
* @param chunk
|
|
|
|
* @return
|
|
|
|
*/
|
2019-11-07 10:28:17 +00:00
|
|
|
private <V extends Future<V>> V submitUnchecked(IQueueChunk chunk) {
|
2019-04-28 17:36:23 +00:00
|
|
|
if (chunk.isEmpty()) {
|
2019-08-18 01:09:09 +00:00
|
|
|
chunk.recycle();
|
|
|
|
Future result = Futures.immediateFuture(null);
|
2019-11-07 10:28:17 +00:00
|
|
|
return (V) result;
|
2019-04-28 17:36:23 +00:00
|
|
|
}
|
2019-05-01 15:45:18 +00:00
|
|
|
|
2019-04-30 16:19:10 +00:00
|
|
|
if (Fawe.isMainThread()) {
|
2020-04-01 00:29:03 +00:00
|
|
|
V result = (V)chunk.call();
|
2020-10-05 17:41:41 +00:00
|
|
|
if (result == null) {
|
2020-04-01 00:29:03 +00:00
|
|
|
return (V) (Future) Futures.immediateFuture(null);
|
2020-10-05 17:41:41 +00:00
|
|
|
} else {
|
2020-04-01 00:29:03 +00:00
|
|
|
return result;
|
|
|
|
}
|
2019-04-30 16:19:10 +00:00
|
|
|
}
|
2019-05-01 15:45:18 +00:00
|
|
|
|
2019-11-07 10:28:17 +00:00
|
|
|
return (V) Fawe.get().getQueueHandler().submit(chunk);
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-08-06 15:29:09 +00:00
|
|
|
public synchronized boolean trim(boolean aggressive) {
|
2019-08-18 01:09:09 +00:00
|
|
|
cacheGet.trim(aggressive);
|
|
|
|
cacheSet.trim(aggressive);
|
2019-04-28 15:44:59 +00:00
|
|
|
if (Thread.currentThread() == currentThread) {
|
|
|
|
lastChunk = null;
|
|
|
|
lastPair = Long.MAX_VALUE;
|
|
|
|
return chunks.isEmpty();
|
|
|
|
}
|
2019-05-01 15:45:18 +00:00
|
|
|
if (!submissions.isEmpty()) {
|
|
|
|
if (aggressive) {
|
|
|
|
pollSubmissions(0, aggressive);
|
|
|
|
} else {
|
|
|
|
pollSubmissions(Settings.IMP.QUEUE.PARALLEL_THREADS, aggressive);
|
|
|
|
}
|
|
|
|
}
|
2019-04-28 15:44:59 +00:00
|
|
|
synchronized (this) {
|
|
|
|
return currentThread == null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
/**
|
2019-08-06 15:29:09 +00:00
|
|
|
* Get a new IChunk from either the pool, or create a new one<br> + Initialize it at the
|
|
|
|
* coordinates
|
|
|
|
*
|
2020-02-23 17:48:22 +00:00
|
|
|
* @param chunkX
|
|
|
|
* @param chunkZ
|
2019-04-28 17:36:23 +00:00
|
|
|
* @return IChunk
|
|
|
|
*/
|
2020-02-23 17:48:22 +00:00
|
|
|
private ChunkHolder poolOrCreate(int chunkX, int chunkZ) {
|
2019-11-07 10:28:17 +00:00
|
|
|
ChunkHolder next = create(false);
|
2020-02-23 17:48:22 +00:00
|
|
|
next.init(this, chunkX, chunkZ);
|
2019-04-28 15:44:59 +00:00
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
2019-04-28 17:36:23 +00:00
|
|
|
@Override
|
2020-09-21 16:09:17 +00:00
|
|
|
public final IQueueChunk getOrCreateChunk(int x, int z) {
|
2020-09-25 14:00:42 +00:00
|
|
|
getChunkLock.lock();
|
|
|
|
try {
|
|
|
|
final long pair = (long) x << 32 | z & 0xffffffffL;
|
|
|
|
if (pair == lastPair) {
|
|
|
|
return lastChunk;
|
|
|
|
}
|
|
|
|
if (!processGet(x, z)) {
|
|
|
|
lastPair = pair;
|
|
|
|
lastChunk = NullChunk.getInstance();
|
|
|
|
return NullChunk.getInstance();
|
|
|
|
}
|
|
|
|
IQueueChunk chunk = chunks.get(pair);
|
|
|
|
if (chunk != null) {
|
|
|
|
lastPair = pair;
|
|
|
|
lastChunk = chunk;
|
|
|
|
}
|
|
|
|
if (chunk != null) {
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
final int size = chunks.size();
|
|
|
|
final boolean lowMem = MemUtil.isMemoryLimited();
|
|
|
|
// If queueing is enabled AND either of the following
|
|
|
|
// - memory is low & queue size > num threads + 8
|
|
|
|
// - queue size > target size and primary queue has less than num threads submissions
|
|
|
|
if (enabledQueue && ((lowMem && size > Settings.IMP.QUEUE.PARALLEL_THREADS + 8) || (size > Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized()))) {
|
2021-01-13 19:02:51 +00:00
|
|
|
chunk = chunks.removeFirst();
|
|
|
|
final Future future = submitUnchecked(chunk);
|
2020-09-25 14:00:42 +00:00
|
|
|
if (future != null && !future.isDone()) {
|
|
|
|
final int targetSize;
|
|
|
|
if (lowMem) {
|
|
|
|
targetSize = Settings.IMP.QUEUE.PARALLEL_THREADS + 8;
|
|
|
|
} else {
|
|
|
|
targetSize = Settings.IMP.QUEUE.TARGET_SIZE;
|
|
|
|
}
|
|
|
|
pollSubmissions(targetSize, lowMem);
|
|
|
|
submissions.add(future);
|
2019-05-01 15:45:18 +00:00
|
|
|
}
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
2020-09-25 14:00:42 +00:00
|
|
|
chunk = poolOrCreate(x, z);
|
|
|
|
chunk = wrap(chunk);
|
2019-04-28 15:44:59 +00:00
|
|
|
|
2020-09-25 14:00:42 +00:00
|
|
|
chunks.put(pair, chunk);
|
|
|
|
lastPair = pair;
|
|
|
|
lastChunk = chunk;
|
2019-04-28 15:44:59 +00:00
|
|
|
|
2020-09-25 14:00:42 +00:00
|
|
|
return chunk;
|
|
|
|
} finally {
|
|
|
|
getChunkLock.unlock();
|
|
|
|
}
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
|
|
|
|
2019-08-18 01:09:09 +00:00
|
|
|
@Override
|
2019-11-07 10:28:17 +00:00
|
|
|
public ChunkHolder create(boolean isFull) {
|
2019-08-18 01:09:09 +00:00
|
|
|
return ChunkHolder.newInstance();
|
|
|
|
}
|
|
|
|
|
2019-08-06 15:29:09 +00:00
|
|
|
private void pollSubmissions(int targetSize, boolean aggressive) {
|
2019-05-02 14:45:03 +00:00
|
|
|
final int overflow = submissions.size() - targetSize;
|
2019-05-01 15:45:18 +00:00
|
|
|
if (aggressive) {
|
2019-10-30 11:26:52 +00:00
|
|
|
if (targetSize == 0) {
|
|
|
|
while (!submissions.isEmpty()) {
|
|
|
|
Future future = submissions.poll();
|
|
|
|
try {
|
2020-10-05 17:41:41 +00:00
|
|
|
while (future != null) {
|
|
|
|
future = (Future) future.get();
|
|
|
|
}
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (FaweException messageOnly) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(messageOnly.getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (ExecutionException e) {
|
|
|
|
if (e.getCause() instanceof FaweException) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} else {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
} catch (InterruptedException e) {
|
2019-10-30 11:26:52 +00:00
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-01 15:45:18 +00:00
|
|
|
for (int i = 0; i < overflow; i++) {
|
|
|
|
Future first = submissions.poll();
|
|
|
|
try {
|
2020-10-05 17:41:41 +00:00
|
|
|
while (first != null) {
|
|
|
|
first = (Future) first.get();
|
|
|
|
}
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (FaweException messageOnly) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(messageOnly.getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (ExecutionException e) {
|
|
|
|
if (e.getCause() instanceof FaweException) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} else {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
} catch (InterruptedException e) {
|
2019-05-01 15:45:18 +00:00
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < overflow; i++) {
|
|
|
|
Future next = submissions.peek();
|
|
|
|
while (next != null) {
|
|
|
|
if (next.isDone()) {
|
|
|
|
try {
|
|
|
|
next = (Future) next.get();
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (FaweException messageOnly) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(messageOnly.getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (ExecutionException e) {
|
|
|
|
if (e.getCause() instanceof FaweException) {
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage());
|
2021-01-13 20:30:22 +00:00
|
|
|
} else {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
2021-03-29 13:29:16 +00:00
|
|
|
LOGGER.error("Please report this error on our issue tracker: https://github.com/IntellectualSites/FastAsyncWorldEdit/issues");
|
2021-02-19 19:19:19 +00:00
|
|
|
e.getCause().printStackTrace();
|
2021-01-13 20:30:22 +00:00
|
|
|
} catch (InterruptedException e) {
|
2019-05-01 15:45:18 +00:00
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
submissions.poll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 15:44:59 +00:00
|
|
|
@Override
|
|
|
|
public synchronized void flush() {
|
|
|
|
if (!chunks.isEmpty()) {
|
2019-05-01 15:45:18 +00:00
|
|
|
if (MemUtil.isMemoryLimited()) {
|
2019-11-07 10:28:17 +00:00
|
|
|
for (IQueueChunk chunk : chunks.values()) {
|
2019-05-02 14:45:03 +00:00
|
|
|
final Future future = submitUnchecked(chunk);
|
2019-05-01 15:45:18 +00:00
|
|
|
if (future != null && !future.isDone()) {
|
|
|
|
pollSubmissions(Settings.IMP.QUEUE.PARALLEL_THREADS, true);
|
|
|
|
submissions.add(future);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2019-11-07 10:28:17 +00:00
|
|
|
for (IQueueChunk chunk : chunks.values()) {
|
2019-05-02 14:45:03 +00:00
|
|
|
final Future future = submitUnchecked(chunk);
|
2019-05-01 15:45:18 +00:00
|
|
|
if (future != null && !future.isDone()) {
|
|
|
|
submissions.add(future);
|
2019-04-30 16:19:10 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.lock();
|
2019-05-01 15:45:18 +00:00
|
|
|
chunks.clear();
|
2021-01-14 15:42:38 +00:00
|
|
|
getChunkLock.unlock();
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
2019-05-01 15:45:18 +00:00
|
|
|
pollSubmissions(0, true);
|
2019-04-28 15:44:59 +00:00
|
|
|
}
|
2019-08-26 04:45:03 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public ChunkFilterBlock initFilterBlock() {
|
|
|
|
return new CharFilterBlock(this);
|
|
|
|
}
|
2021-01-11 19:29:16 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public ProcessorScope getScope() {
|
|
|
|
return ProcessorScope.ADDING_BLOCKS;
|
|
|
|
}
|
2019-07-25 19:09:12 +00:00
|
|
|
}
|