forked from lishid/Orebfuscator
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: WIP - async obfuscation * feat: WIP - async ChunkSerializer + ChunkCache * feat: async ChunkCache * feat: improve AsyncChunkSerializer (task grouping) * feat: improve AsyncChunkSerializer efficiency * fix: memory-leak on reload in ProximityHider * feat: ofc thread group + thread names * feat: added new config options for new async cache
- Loading branch information
Showing
28 changed files
with
528 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
160 changes: 160 additions & 0 deletions
160
orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/cache/AsyncChunkSerializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package net.imprex.orebfuscator.cache; | ||
|
||
import java.io.IOException; | ||
import java.util.HashMap; | ||
import java.util.LinkedList; | ||
import java.util.Map; | ||
import java.util.Queue; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.locks.Condition; | ||
import java.util.concurrent.locks.Lock; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
import net.imprex.orebfuscator.Orebfuscator; | ||
import net.imprex.orebfuscator.obfuscation.ObfuscatedChunk; | ||
import net.imprex.orebfuscator.util.ChunkPosition; | ||
|
||
public class AsyncChunkSerializer implements Runnable { | ||
|
||
private final Lock lock = new ReentrantLock(); | ||
private final Condition notFull = lock.newCondition(); | ||
private final Condition notEmpty = lock.newCondition(); | ||
|
||
private final Map<ChunkPosition, Runnable> tasks = new HashMap<>(); | ||
private final Queue<ChunkPosition> positions = new LinkedList<>(); | ||
private final int maxTaskQueueSize; | ||
|
||
private final Thread thread; | ||
private volatile boolean running = true; | ||
|
||
public AsyncChunkSerializer(Orebfuscator orebfuscator) { | ||
this.maxTaskQueueSize = orebfuscator.getOrebfuscatorConfig().cache().maximumTaskQueueSize(); | ||
|
||
this.thread = new Thread(Orebfuscator.THREAD_GROUP, this, "ofc-chunk-serializer"); | ||
this.thread.setDaemon(true); | ||
this.thread.start(); | ||
} | ||
|
||
public CompletableFuture<ObfuscatedChunk> read(ChunkPosition position) { | ||
this.lock.lock(); | ||
try { | ||
Runnable task = this.tasks.get(position); | ||
if (task instanceof WriteTask) { | ||
return CompletableFuture.completedFuture(((WriteTask) task).chunk); | ||
} else if (task instanceof ReadTask) { | ||
return ((ReadTask) task).future; | ||
} else { | ||
CompletableFuture<ObfuscatedChunk> future = new CompletableFuture<>(); | ||
this.queueTask(position, new ReadTask(position, future)); | ||
return future; | ||
} | ||
} finally { | ||
this.lock.unlock(); | ||
} | ||
} | ||
|
||
public void write(ChunkPosition position, ObfuscatedChunk chunk) { | ||
this.lock.lock(); | ||
try { | ||
Runnable prevTask = this.queueTask(position, new WriteTask(position, chunk)); | ||
if (prevTask instanceof ReadTask) { | ||
((ReadTask) prevTask).future.complete(chunk); | ||
} | ||
} finally { | ||
this.lock.unlock(); | ||
} | ||
} | ||
|
||
private Runnable queueTask(ChunkPosition position, Runnable nextTask) { | ||
while (this.positions.size() >= this.maxTaskQueueSize) { | ||
this.notFull.awaitUninterruptibly(); | ||
} | ||
|
||
if (!this.running) { | ||
throw new IllegalStateException("AsyncChunkSerializer already closed"); | ||
} | ||
|
||
Runnable prevTask = this.tasks.put(position, nextTask); | ||
if (prevTask == null) { | ||
this.positions.offer(position); | ||
} | ||
|
||
this.notEmpty.signal(); | ||
return prevTask; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
while (this.running) { | ||
this.lock.lock(); | ||
try { | ||
if (this.positions.isEmpty()) { | ||
this.notEmpty.await(); | ||
} | ||
|
||
this.tasks.remove(this.positions.poll()).run(); | ||
|
||
this.notFull.signal(); | ||
} catch (InterruptedException e) { | ||
break; | ||
} finally { | ||
this.lock.unlock(); | ||
} | ||
} | ||
} | ||
|
||
public void close() { | ||
this.lock.lock(); | ||
try { | ||
this.running = false; | ||
this.thread.interrupt(); | ||
|
||
while (!this.positions.isEmpty()) { | ||
Runnable task = this.tasks.remove(this.positions.poll()); | ||
if (task instanceof WriteTask) { | ||
task.run(); | ||
} | ||
} | ||
} finally { | ||
this.lock.unlock(); | ||
} | ||
} | ||
|
||
private class WriteTask implements Runnable { | ||
private final ChunkPosition position; | ||
private final ObfuscatedChunk chunk; | ||
|
||
public WriteTask(ChunkPosition position, ObfuscatedChunk chunk) { | ||
this.position = position; | ||
this.chunk = chunk; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
try { | ||
ChunkSerializer.write(position, chunk); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
|
||
private class ReadTask implements Runnable { | ||
private final ChunkPosition position; | ||
private final CompletableFuture<ObfuscatedChunk> future; | ||
|
||
public ReadTask(ChunkPosition position, CompletableFuture<ObfuscatedChunk> future) { | ||
this.position = position; | ||
this.future = future; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
try { | ||
future.complete(ChunkSerializer.read(position)); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.