-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Assuming to have a virtual thread (only) which call N times Thread::yield, it will re-run itself immediately till exhausting the available yield limits (see 249b4b9).
It would be nicer if a Thread::yield from a virtual thread different from the event loop can just enable running the event loop.
In short, having something like:
@Override
public void execute(Runnable command) {
if (ioEventLoop.isTerminated()) {
throw new RejectedExecutionException("event loop is shutting down");
}
// The default scheduler won't shut down, but Netty's event loop can!
Runnable eventLoopContinuation = this.eventLoopContinuation;
if (eventLoopContinuation == null) {
eventLoopContinuation = setEventLoopContinuation(command);
}
if (eventLoopContinuation == command) {
submittedEventLoopContinuation = true;
} else {
// <--------------------- Thread::yield should happen in the carrier
if (Thread.currentThread() == carrierThread && externalContinuations.isEmpty() && submittedEventLoopContinuation) {
// if we have an event loop to run and no other tasks...
externalContinuations.offer(command)
// let's just resume the event loop, if it needs
submittedEventLoopContinuation = false;
eventLoopContinuation.run();
// here shouldn't need to wake up the event loop, but needs investigation!
return;
// <---------------------
} else {
externalContinuations.offer(command)
}
}
if (!ioEventLoop.inEventLoop(Thread.currentThread())) {
// TODO: if we have access to the scheduler brought by the continuation,
// we could skip the wakeup if matches with this.
ioEventLoop.wakeup();
LockSupport.unpark(parkedCarrierThread);
} else if (eventLoopContinuation != command && !running.get()) {
// since the event loop was blocked, it's fine if we try to consume some continuations, if any
Thread.yield();
}
}Clearly this is going to improve Thread::yield reactivity for a single virtual thread doing it; if we have 2 virtual threads which Thread::yield, it won't work.
And, if the event loop is operating on a resource which we expect the Thread::yield on the virtual thread to grant room to make some progress, it will fail.
In short; even with this "workaround" the problem of fairly grant progress to everyone, is not fixed.
A potentially better solution would be to give all virtual thread (including the event loop) a similar bandwidth (i.e. chances to be executed for some amount of time) - but since the event loop I/O cannot be "stopped", I'm not sure is something we could address.