Open ysbaddaden opened 4 months ago
We have a couple use cases where the ability to detach a scheduler from a thread would be useful:
getaddrinfo
is a blocking C call, it can be very slow in some situations, taking seconds if not minutes to resolve (or fail to resolve); during all this time a whole thread will be blocked and if you have only one thread then even signals (such as SIGINT) won't be processed.
For this use-case we can try to reattach or merely reenqueue the fiber. There's no issue.
libxml2
is thread safe (now), and saves its global state in thread local storage, but it's not concurrency safe, where multiple fibers parsing from or writing to sockets or pipes concurrently will mess the global state; even worse with EC::MT when a fiber may be resumed in another thread :scream:
A solution could be to make the IO blocking while libxml2 tries to read or write and detach the scheduler from the thread.
:warning: for this use case, the thread must continue to run even if it failed to reattach the scheduler, and must do so until the fiber yields... so maybe it's not the best solution :thinking:
Why do we need to make IO blocking? I figure it could just stay async as it is, even keep attached to the event loop. But when a pinned fiber resumes, it can do so instantly (no enqueue) because it has its own thread just waiting for it.
Why bother with the evloop if we block the thread anyway? We can just do a blocking read/write syscall since we "own" the thread...
...because that would only work for the polling & libevent evloops, and IOCP for example doesn't allow to change the blocking state. Damn.
The MT context could have M schedulers running on N threads (where M < N), along with the ability to actively move a scheduler to another thread.
For example when the monitor thread notices that a fiber has been running for too long, it could detach the scheduler from the thread its running on (keeping the CPU-bound fiber running) and try to attach it to a sleeping thread, or add it to a list of pickable schedulers when all threads are busy.
When the fiber finally yields, the thread can try to reattach the scheduler it was previously running, or try to pick another one, or go to sleep.