Events
"이희승 (Trustin Lee)"
trustin at gmail.com
Mon Jun 8 06:34:44 EDT 2009
On 08-Jun-2009 19:03, Yang Zhang wrote:
> 이희승 (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.
Ah, I see. I think the second example is pretty good to describe the
problem IIUC. I experienced the same issue when I implement SslHandler
actually: http://tinyurl.com/m3dfsb I worked around the issue by using
Thread.holdsLock(). Your idea would definitely simplify the
implementation. Not sure how easy it will be to implement your idea
though. Patch welcome. :)
Thanks,
Trustin
--
— Trustin Lee, http://gleamynode.net/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 258 bytes
Desc: OpenPGP digital signature
Url : http://lists.jboss.org/pipermail/netty-users/attachments/20090608/33de25ae/attachment.bin
More information about the netty-users
mailing list