On Oct 4, 2005, at 4:06 AM, Tanaka Akira wrote:

> 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.

Yes, the code I posted made some simplifying assumptions.  If some of  
the data was not written, you need to account for that somehow.  The  
options you suggest would work for ensuring that the write happens  
eventually.  But a nice thing about doing everything in a single  
thread is that you can do better if you choose.

Imagine that you start with world W1.  You get a message from client  
A that updates the state of the world to W2.  Call DELTA1 the message  
you have to send to B and C to update them to W2.  You try to write  
DELTA1 to B, but C is not ready.  The next time through your event  
loop, you get a message from client B updating the state of the world  
to W3.  DELTA2 updates W2 to W3, so you send that to A, but C is  
still not ready.

Once C becomes ready, you could send C DELTA1 and DELTA2, or you  
could be smart and combine those into a single DELTA3 that updates W1  
to W3.  DELTA3 will likely be smaller than DELTA1 + DELTA2.  If you  
had initially blocked-on-write to send DELTA1, you would not have  
that option.

Josh