Ensuring all pending writes complete before close

"이희승 (Trustin Lee)" trustin at gmail.com
Sun Aug 16 21:51:58 EDT 2009


On 08/12/2009 05:52 PM, Iain McGinniss wrote:
> 
> On 12 Aug 2009, at 03:20, 이희승 (Trustin Lee) wrote:
> 
>> Hi Iain,
>>
>> On 08/06/2009 11:47 PM, Iain McGinniss wrote:
>>>
>>> 1. Allowing all pending writes to be completed before I close the
>>> channel.
>>
>> You can achieve this pretty simply:
>>
>>  channel.write(ChannelBuffers.EMPTY_BUFFER)
>>         .addListener(ChannelFutureListener.CLOSE);
> 
> Netty is hidden beneath several layers of abstraction, so it is  
> difficult for me to expose this kind of write-then-close semantics  
> where it is needed. The code right now is more akin to
> 
> pipe.write(message);
> pipe.close();
> 
> Where pipe.close() should not return until all pending writes are  
> completed and the channel is closed, or some error condition occurs  
> and the pipe is closed.
> 
>>
>>> 2. Preventing new writes from being requested during shutdown.
>>
>> This is more tricky.  You could maintain a boolean flag as you  
>> mentioned
>> above.  An alternative is to write a handler that discards or rejects
>> any write requests and insert the handler into the pipeline right  
>> after
>> you write an EMPTY_BUFFER.
> 
> 
> 
>>
>>> 3. Allow for the entity that requested the close to wait for the
>>> channel to close using the standard mechanism.
>>
>> I don't follow this.  Could you elaborate?
> 
> All I meant here was that I could call  
> channel.close().awaitUninterruptibly(), and that this wouldn't be  
> affected by whatever mechanism I had chosen to ensure all writes would  
> be performed before the close would occur.
> 
> The technique I went for in the end involved handling closeRequested()  
> in my handler, and flipping a boolean to indicate we were closing the  
> channel. For every write handled via writeRequested(), I stored the  
> ChannelFuture for that write and added a listener to it, placing the  
> ChannelFuture into a set. Once the closing flag is set, all future  
> write requests are simply ignored (with a WARNING log). For each call  
> to operationComplete on my ChannelFutureListener, I remove that future  
> from the pending set. Once the pending set is empty, I send the close  
> request downstream. In the simple case, with a quiet channel,  
> closeRequested can directly see that the pending set is empty and so  
> can immediately send the close request downstream.
> 
> This appears to work, I'm using a ReentrantLock for concurrency  
> control but I think there is a way to do it using less explicit  
> locking (using an AtomicInteger count of pending writes, for instance).

This could be implemented as a separate ChannelHandler implementation
and provided as an official part of Netty.  Let me know if you are
interested in contribution.

> There are a lot of interesting problems like this in network  
> programming, that Netty could really benefit from having good examples  
> of in the documentation. I believe this would help illuminate the  
> problems that people will face with a fully asynchronous, concurrent  
> networking stack.

Agreed.  I'd like to write a couple more chapters for 3.2.  Please also
note that we have a wiki page for user-contributed examples:

  * http://www.jboss.org/community/wiki/Netty

The examples there are much more complicated than those in the official
distribution, but they are intended to be more useful to those who want
something more real-worldish.

HTH,
Trustin



More information about the netty-users mailing list