olegst
olegst

Reputation: 1267

Non-blocking I/O issue

I don't have much experience with asynchronous I/O on sockets. Recently I had to implement a TCP client that would connect to a server in a seperate thread and wait for input data and that in a non-blocking manner so that the thread could be terminated immediately by simply setting some flag varaible from the control thread. My solution was setting socket non-blocking and implementing a loop that called recv over and over again if errno was E_WOULDBLOCK and exited loop when flag variable run wasn't set anymore. It was like that:

while(run) {
   if( -1 == recv(...))
   {
       if(errno == E_WOULDBLOCK)
            continue; 
       else
            break; 
   }
   else
   {
       process_data(...); 
   }
}

The question is: how good is this solution in terms of CPU usage? Will using select/poll/epoll be more effective?

And another one question: is there any way to make blocked select, read or connnect call return immediately from other thread?

Upvotes: 0

Views: 1865

Answers (3)

edmz
edmz

Reputation: 8494

The question is: how good is this solution in terms of CPU usage? Will using select/poll/epoll be more effective?

It is terribly inefficient. It is probably the worst way you handle multiple connections. Consider that each recv is a system call: it requires a context switch. A context switch is not expensive, but computing a context switch in a high frequency loop will likely full the CPU usage. Also, if you were to sleep between a call and another, to "soften the loop", you would end up paying a delay between data receive and processing; the more connections you have, the higher it'll be felt.

select basically tells the kernel: "I want these sets of fds to be monitored by you and also be signaled as soon as something happens.". Your process will enter a waiting state and become ready when an event is delivered. Meanwhile, the CPU may serve other processes.

You may use a blocking multiplexer and handle each work in a separate thread (maybe from a thread pool), which is very efficient. But it depends on what you're doing.

And another one question: is there any way to make blocked select, read or connnect call return immediately from other thread?

Well, yes. But is something you want to have? As @alk said, you can send them a signal. In addition, for recv and connect, you might want to use select/poll or any other multiplexer with timeout properties; it might be harder to program, though.

Upvotes: 2

alk
alk

Reputation: 70903

how good is this solution in terms of CPU usage?

Busy waiting is very inefficient.

Will using select/poll/epoll be more effective?

Yes.

is there any way to make blocked select, read or connnect return immediately

Yes, send the blocked thread a signal. The function in question will return -1 and errno shall be set to EINTR. When setting up the signal handler take care of how SA_RESTART is handled by your compiler's implementation.

Upvotes: 2

5gon12eder
5gon12eder

Reputation: 25409

Assuming you are programming in C and have a decent kernel version, pselect is the way to go.

Waiting for input and signals simultaneously is a well-known problem and there are many good discussions about the problems and solutions associated with it. You might find this discussion a good start.

Upvotes: 0

Related Questions