Events

Yang Zhang yanghatespam at gmail.com
Mon Jun 8 06:03:39 EDT 2009


이희승 (Trustin Lee) wrote:
> On 08-Jun-2009 16:28, Yang Zhang wrote:
>> 이희승 (Trustin Lee) wrote:
>>> On 08-Jun-2009 14:11, Yang Zhang wrote:
>>>> 이희승 (Trustin Lee) wrote:
>>>>> On 07-Jun-2009 16:46, Yang Zhang wrote:
>>>>>> Hi,
>>>>>>
>>>>>> 이희승 (Trustin Lee) wrote:
>>>>>>> You can issue a new event by calling Channels.fireXXX(...),
>>>>>>> ChannelPipeline.sendUpstream/Downstream(...), or
>>>>>>> ChannelHandlerContext.sendUpstream/Downstream(...).  However, the
>>>>>>> call
>>>>>>> is made recursively.
>>>>>> The fact that the call is made recursively is problematic: the code
>>>>>> immediately following the async call is expected to immediately
>>>>>> execute
>>>>>> (at least, before the callback is executed), but with the recursive
>>>>>> call, the callback will execute *in the same thread and before* the
>>>>>> code
>>>>>> immediately following the call.
>>>>> In asynchronous I/O, you can't make any assumption on when and how an
>>>>> asynchronous request will be executed.  The point of the asynchronous
>>>>> I/O is, IMHO, it returns as quickly as possible, possibly before the
>>>>> request is processed.
>>>> It's fine for the async IO to complete before the request is processed
>>>> (since, as you notice, you have no control over the timing), but the
>>>> problem here is that it's firing recursively within the same event call
>>>> stack.
>>> Could you elaborate on why a recursive event call is a problem?  I guess
>>> I'm missing out something.
>> The call site must be prepared for the event to not try to execute
>> concurrently in a way that blocks itself.  A simple example:
>>
>>   final SynchronizedQueue<Result> queue = ...;
>>   Callback callback = new Callback() {
>>     public void callback(Result x) { queue.put(x); }
>>   };
>>   doSomethingAsynchronous(..., callback);
>>   Result r = queue.get();
>>
>> This halts.  The way around this is to push the put or the get into a
>> separate thread, but that's clumsy at best, requiring the user to either
>> create a new thread or manage her own thread pool (outside Netty's own
>> thread pool).  It furthermore requires an extra thread even in
>> applications that limit themselves to a single event-handling thread.
> 
> Did you mean SynchronousQueue or just synchronized Queue?  If you meant
> a plain synchronized queue, it does not halt but can throw an NPE as
> expected.
> 
> If SynchronousQueue were used, as you pointed out, it does not work
> because either put() or get() will wait for get() or put() respectively
> and Netty usually does not execute callback and handler of the same
> channel simultaneously.
> 
> However, it's not a recursive call that causes the race condition but is
> two dependent tasks being executed in order in the same thread.  How
> does non-recursive event / callback execution solve this issue?

You're right that in a single-threaded reactor, this would not be able 
to proceed, so ignore the last sentence that I threw in there.  A 
non-recursive event execution would solve this because the event would 
be fired in a separate thread (assuming that multiple threads can wait 
for events).

The latter example I gave is probably the stronger of the two.
-- 
Yang Zhang
http://www.mit.edu/~y_z/



More information about the netty-users mailing list