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