From 100afadd5c6a10725ccb96386fc6fec7ce6b6763 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 19 Apr 2024 11:27:55 +0700 Subject: [PATCH] Blockable event loop without locking --- .../kstarbound/util/BlockableEventLoop.kt | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/BlockableEventLoop.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/BlockableEventLoop.kt index 8315d9a2..bb2d8e96 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/util/BlockableEventLoop.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/BlockableEventLoop.kt @@ -9,6 +9,7 @@ import org.apache.logging.log4j.LogManager import java.util.PriorityQueue import java.util.concurrent.Callable import java.util.concurrent.CompletableFuture +import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.Delayed import java.util.concurrent.Future import java.util.concurrent.FutureTask @@ -81,13 +82,13 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer private class TaskPair(val future: CompletableFuture, var supplier: Callable?) - private val eventQueue = LinkedBlockingQueue>() + private val eventQueue = ConcurrentLinkedQueue>() private val scheduledQueue = PriorityQueue>() val coroutines = asCoroutineDispatcher() val scope = CoroutineScope(coroutines + SupervisorJob()) private fun nextDeadline(): Long { - if (isShutdown) + if (isShutdown || eventQueue.isNotEmpty()) return 0L val poll = scheduledQueue.peek() @@ -105,7 +106,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer private fun eventLoopIteration(): Boolean { var executedAnything = false - val next = eventQueue.poll(nextDeadline(), TimeUnit.NANOSECONDS) + val next = eventQueue.poll() if (next != null) { executedAnything = true @@ -152,6 +153,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer final override fun run() { while (isRunning) { + LockSupport.parkNanos(nextDeadline()) eventLoopIteration() if (isShutdown && isRunning) { @@ -180,6 +182,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer } eventQueue.add(pair) + LockSupport.unpark(this) } } @@ -203,6 +206,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer } eventQueue.add(pair) + LockSupport.unpark(this) return future } } @@ -240,6 +244,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer } eventQueue.add(pair) + LockSupport.unpark(this) return future } } @@ -265,6 +270,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer } eventQueue.add(pair) + LockSupport.unpark(this) return future } } @@ -321,7 +327,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer performShutdown() } else { // wake up thread - eventQueue.add(TaskPair(CompletableFuture()) { }) + LockSupport.unpark(this) } } } @@ -359,7 +365,8 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer scope.cancel(CancellationException("EventLoop shut down")) performShutdown() } else { - eventQueue.add(TaskPair(CompletableFuture()) { }) + // wake up thread + LockSupport.unpark(this) } }