Blockable event loop without locking

This commit is contained in:
DBotThePony 2024-04-19 11:27:55 +07:00
parent a66de1133a
commit 100afadd5c
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -9,6 +9,7 @@ import org.apache.logging.log4j.LogManager
import java.util.PriorityQueue import java.util.PriorityQueue
import java.util.concurrent.Callable import java.util.concurrent.Callable
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.Delayed import java.util.concurrent.Delayed
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.FutureTask import java.util.concurrent.FutureTask
@ -81,13 +82,13 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
private class TaskPair<T>(val future: CompletableFuture<T>, var supplier: Callable<T>?) private class TaskPair<T>(val future: CompletableFuture<T>, var supplier: Callable<T>?)
private val eventQueue = LinkedBlockingQueue<TaskPair<*>>() private val eventQueue = ConcurrentLinkedQueue<TaskPair<*>>()
private val scheduledQueue = PriorityQueue<ScheduledTask<*>>() private val scheduledQueue = PriorityQueue<ScheduledTask<*>>()
val coroutines = asCoroutineDispatcher() val coroutines = asCoroutineDispatcher()
val scope = CoroutineScope(coroutines + SupervisorJob()) val scope = CoroutineScope(coroutines + SupervisorJob())
private fun nextDeadline(): Long { private fun nextDeadline(): Long {
if (isShutdown) if (isShutdown || eventQueue.isNotEmpty())
return 0L return 0L
val poll = scheduledQueue.peek() val poll = scheduledQueue.peek()
@ -105,7 +106,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
private fun eventLoopIteration(): Boolean { private fun eventLoopIteration(): Boolean {
var executedAnything = false var executedAnything = false
val next = eventQueue.poll(nextDeadline(), TimeUnit.NANOSECONDS) val next = eventQueue.poll()
if (next != null) { if (next != null) {
executedAnything = true executedAnything = true
@ -152,6 +153,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
final override fun run() { final override fun run() {
while (isRunning) { while (isRunning) {
LockSupport.parkNanos(nextDeadline())
eventLoopIteration() eventLoopIteration()
if (isShutdown && isRunning) { if (isShutdown && isRunning) {
@ -180,6 +182,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
} }
eventQueue.add(pair) eventQueue.add(pair)
LockSupport.unpark(this)
} }
} }
@ -203,6 +206,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
} }
eventQueue.add(pair) eventQueue.add(pair)
LockSupport.unpark(this)
return future return future
} }
} }
@ -240,6 +244,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
} }
eventQueue.add(pair) eventQueue.add(pair)
LockSupport.unpark(this)
return future return future
} }
} }
@ -265,6 +270,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
} }
eventQueue.add(pair) eventQueue.add(pair)
LockSupport.unpark(this)
return future return future
} }
} }
@ -321,7 +327,7 @@ open class BlockableEventLoop(name: String) : Thread(name), ScheduledExecutorSer
performShutdown() performShutdown()
} else { } else {
// wake up thread // 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")) scope.cancel(CancellationException("EventLoop shut down"))
performShutdown() performShutdown()
} else { } else {
eventQueue.add(TaskPair(CompletableFuture()) { }) // wake up thread
LockSupport.unpark(this)
} }
} }