views:

221

answers:

6

I know non-blocking receive is not used as much in message passing, but still some intuition tells me, it is needed. Take for example GUI event driven applications, you need some way to wait for a message in a non-blocking way, so your program can execute some computations. One of the ways to solve this is to have a special thread with message queue. Is there some use case, where you would really need non-blocking receive even if you have threads?

+1  A: 

I can't think of any, but sometimes the non-blocking APIs are designed in a way that makes them easier/more intuitive to use than an explicitly multi-threaded implementation.

500 - Internal Server Error
I think nowadays there are more concurrent models which tend to be easier to use, so I don't think this is very valid.
Gabriel Ščerbák
+4  A: 

Threads work differently than non-blocking asynchronous operations, although you can usually achieve the same effect by having threads that does synchronous operations. However, in the end, it boils down on how to handle doing things more efficiently.

Threads are limited resources, and should be used to process long running, active operations. If you have something that is not really active doing things, but need to wait idly for some time for the result (think some I/O operation over the network like calling web services or database servers), then it is better to use the provided asynchronous alternative for it instead of wasting threads unnecessarily by putting the synchronous call on another thread.

You can have a good read on this issue here for more understanding.

Amry
Just about what I was going to answer. I would have also mentioned select() but that's not as universal as one would hope. If one can handle 500 connections per thread, one process might be able to handle 250,000 connections.
Joshua
Yeah, and if one thread could handle 1,000,000 connections you might be able to handle 1,000,000,000 connections!But yeah, of course I agree, if you can multiplex one thread over a bunch of connections (using select, poll, kqueue, WaitForMultipleObjects... whatever) you should, it scales much better.
MK
On Windows platforms you can use I/O completion ports and asynchronous I/O to handle 10s of thousands of active connections and pending I/O requests with very few (we're talking 2-4) threads...
Len Holgate
You run into other problems long before you get to the mythical billion. For one thing, the OS will probably crap out in the "few thousand simultaneous" range...
Donal Fellows
thank you for your answer, but I would like to hear some arguments ignoring the fact, that there is limited amount of threads, because that can change easily. Look at my own anser please and comment, thank yoou! I will be loooking into the article soon....
Gabriel Ščerbák
+2  A: 

One thread per connection is often not a good idea (wasted memory, not all OS are very good with huge thread counts, etc)

How do you interrupt the blocking receive call? On Linux, for example (and probably on some other POSIX OS) pthreads + signals = disaster. With a non-blocking receive you can multiplex your wait on the receiving socket and some kind of IPC socket used to communicate between your threads. Also maps to the Windows world relatively easily.

If you need to replace your regular socket with something more complex (e.g. OpenSSL) relying on the blocking behavior can get you in trouble. OpenSSL, for example, can get deadlocked on a blocking socket, because SSL protocol has sender/receive inversion scenarios where receive can not proceed before some sending is done.

My experience has been -- "when in doubt use non-blocking sockets".

MK
Hmm, so you see the problem in a potential deadlock, that is interesting. You also mention synchronization and communication between threads (implicitly), can you provide some minimalistic example where it is harder to implement the communication between threads than effective calling of non-blocking operations? That is something I hinted at in my own answer to my question...
Gabriel Ščerbák
Here is the thread discussing a deadlock in OpenSSL caused by blocking sockets: http://marc.info/?t=114988489900003 you can't implement this elegantly without non-blocking sockets. Things get even more beautiful (but somewhat harder to understand) with async sockets (io completions), but non-blocking event-driven sockets provide you both simplicity and efficiency.
MK
I strongly recommend you to check out http://www.mailinator.com/tymaPaulMultithreaded.pdf
Peter Štibraný
I can't really read powerpoint slides efficiently, but there is no source code for his benchmark and I suspect he was doing 1 thread for all connections in the NIO test which is not the best way of doing things, you should have one thread handle 5-60 connections depending on a bunch of things. Also it is not clear to me that things extrapolate cleanly from Java to everything else.
MK
A: 

My point is, that when we consider threads and messaging being perfect, the real trade-off is about writing scheduler for planning the non-blocking receive operations and writing synchronizations codefor threads with shared state (locks etc.). I would say, that both can be sometime easy and sometime hard. So an use case would be when there are many messages asynchronous messages to be received and when there is much data to be operated on based on the messages. This would be quite easy in one thread using non-blocking receive and would ask for much synchronization with many threads and shared state.... I am also thinking about some real life example, I will include it probably later.

Gabriel Ščerbák
+1  A: 

Here goes a real situation I have faced recently. Formerly I had a script that would run every hour, managed by crontab, but sometimes users would log to the machine and run the script manually. This had some problems, for example concurrent execution by crontab and user could cause problems, and sometimes users would log in as root - I know, bad pattern, not under my control - and run script with wrong permissions. So we decided to have the routine running as daemon, with proper permissions, and the command users were used to run would now just trigger the daemon.

So, this user executed command would basically do two things: trigger the daemon and wait for it to finish the task. But it also needed a timeout and to keep dumping daemon logs to user while waiting.

If I understand the situation you proposed, I had the case you want: I needed to keep listening from daemon while still interacting with user independently. The solution was asynchronous read.

Lucky for me, I didn't think about using threads. I probably would have thought so if I were coding in Java, but this was Python code.

lfagundes
Good example of non-blocking receive, however I have not understood how is this better than threads in your opinion. However, I gave you upvote, I appreciate experience and effort given in answering.
Gabriel Ščerbák
For me what is better is what solves the problem as simple as possible :-). As I said, if I used java I would probably go to threads because java threading support is very good and synchronization is simple, while in python this support is not so good. I guess each solution has its pros and cons, and when you say one is better you must have parameters on what matters most in your case. So far my experience with threads was good for heavy multitasking with shared memory in c++ and java, but got much better results with fork in perl and python.
lfagundes
+2  A: 

With blocking IO, it's challenging on many platforms to get your application to do a best effort orderly shutdown in the face of slow, hung, or disconnected clients/services.

With non-blocking IO, you can kill the in-flight operation as soon as the system call returns, which is immediately. If your code is written with premature termination in mind - which is comparatively simple with non-blocking IO - this can allow you to clean up your saved state gracefully.

Jason