Let’s say that I have two libraries (A and B), and each has one function that listen on sockets. These functions use select() and they return some event immediately if the data has arrived, otherwise they wait for some time (timeout) and then return NULL:
A_event_t* A_wait_for_event(int timeout);
B_event_t* B_wait_for_event(int timeout);
Now, I use them in my program:
int main (int argc, char *argv[]) {
// Init A
// Init B
// .. do some other initialization
A_event_t *evA;
B_event_t *evB;
for(;;) {
evA = A_wait_for_event(50);
evB = B_wait_for_event(50);
// do some work based on events
}
}
Each library has its own sockets (e.g. udp socket) and it is not accessible from outside.
PROBLEM: This is not very efficient. If for example there is a lot of events waiting to be delivered by *B_wait_for_event* these would have to wait always until *A_wait_for_event* timeouts, which effectively limits the throughput of library B and my program.
Normally, one could use threads to separate processing, BUT what if processing of some event require to call function of other library and vice verse. Example:
if (evA != 0 && evA == A_EVENT_1) {
B_do_something();
}
if (evB != 0 && evB == B_EVENT_C) {
A_do_something();
}
So, even if I could create two threads and separate functionality from libraries, these threads would have to exchange events among them (probably through pipe). This would still limit performance, because one thread would be blocked by *X_wait_for_event()* function, and would not be possible to receive data immediately from other thread.
How to solve this?
(I’m moving this to an answer since it’s getting too long for a comment)
If you are in a situation where you’re not allowed to call
A_do_somethingin one thread while another thread is executingA_wait_for_event(and similarly forB), then I’m pretty sure you can’t do anything efficient, and have to settle between various evils.The most obvious improvement is to immediately take action upon getting an event, rather than trying to read from both: i.e. order your loop
Other mitigations you could do are
EDIT: You might check the APIs for your library; they might already offer a way to deal with the problem. For example, they might allow you to register callbacks for events, and get notifications of events through the callback, rather than polling
wait_for_event.Another thing is if you can create new file descriptors for the library to listen on. e.g. If you create a new pipe and hand one end to library
A, then if thread #1 is waiting for anAevent, thread #2 can write to the pipe to make an event happen, thus forcing #1 out ofwait_for_event. With the ability to kick threads out of thewait_for_eventfunctions at will, all sorts of new options become available.