In article <659657CD-D443-45AD-8006-0458433CF365 / reverberate.org>,
  Joshua Haberman <joshua / reverberate.org> writes:

> Nonblocking I/O is useful if you are a server with some kind of  
> complex, global state, and lots of clients that can act on that  
> state.  A good example would be a gaming server.  If you handle every  
> client in its own thread, you need a big, coarse lock around your  
> global state.  Once you're doing that, what's the point of  
> multithreading?  It just makes things more complicated, and your  
> program's execution more difficult to understand.

I see.

> while true
>      (read_ready, write_ready, err) = IO.select([A, B, C])
>      read_ready.each { |io|
>          output = process(io.read)
>          [A, B, C].each { |client| client.write(output) unless client  
> == io }
>      }
> end

It seems too simplified to explain nonblocking I/O problem.

O_NONBLOCK is required to avoid that write(2) blocks entire
process.  But if write(2) doesn't block due to O_NONBLOCK,
some data are not written.  So the result of write(2) should
be checked and remaining data should be try to write later.

It can be implemented by two ways.

1. Using event driven framework and register an event
   handler for writability to the client.  Since the event
   handler must not block, it needs a nonblocking write
   operation.

2. Using a writing thread dedicated for the client.
   Since the thread is dedicated for the writing, it can use
   a blocking write operation.
-- 
Tanaka Akira