2 ms·
By `standard` I mean a system that works on this platform for any kind of fd or handle. select() is just fine for simple cases, but of course it has some know
by jstimpfle 5y ago
By `standard` I mean a system that works on this platform for any kind of fd or handle.
select() is just fine for simple cases, but of course it has some known problems, such as MAX_FD. There are better APIs, and ultimately it was learned that ringbuffers between the user-process and the kernel (that remove the need for system calls) as an implementation of asynchronous I/O are a good idea. I.e. IOCP, io_uring, etc.
Often you don't need any of these APIs at all - in a system with a constant ("stochastic") load you don't really need any kind of event waiting system. Instead, you can process all incoming messages every N milliseconds or so.
> Callbacks are the simplest primitive for async code.
No, the simplest thing is to just use a plain old buffer. See e.g. the IOCP API or just any regular buffer code. One side pushes the message to a buffer. Some (arbitrary) time later, the other side (potentially, but not necessarily a different thread) pulls the message from the buffer and handles it.
It's just buffers, buffers are all that is needed, and buffers plainly are the best way to solve all issues related to event handling. No fancy abstract template insanity, no weird generic resource handling systems, no complex scheduling systems, not even a need to declare any kind of event handling function or interface. Just place a few statically allocated buffers at the connection points where threads of execution (OS threads, but also hardware / network etc.) meet.
Callbacks are of course theoretically equivalent, since they can be made to do the same thing as buffers. You can trivially write a callback that only pushes the message to a buffer. In practice, the difference is significant because lots of callback boilerplate is created and temporal coupling (i.e. same thread, same code path) between enqueuing a message and handling the message is encouraged. This results in a lot of overly complex code, including custom green thread runtimes. I've seen it, I've tried to do the same, I've seen others try to do the same. It turns out to be a very, very bad idea, resulting in the creation of a whole parallel universe with separate green threads I/O implementations.
This is what the term "Callback Hell" was invented for.
Look at Windows Fibers API, it's widely recognized to be a dead end. You will find some good post-mortem material on that topic on the internet.