Events

"이희승 (Trustin Lee)" trustin at gmail.com
Mon Jun 8 05:31:19 EDT 2009


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?

In this case, to make them executed simultaneously, I would just add
ExecutionHandler to the pipeline, then callbacks and handlers will be
executed concurrently.

>>>>> The blocking syscall (e.g. select) made at the core of any
>>>>> asynchronous
>>>>> IO framework comes with a timeout parameter, which the framework
>>>>> can use
>>>>> for asynchronous sleeps.  The framework manages a priority queue of
>>>>> "sleep" events, and wakes them up at the appropriate times using this
>>>>> timeout mechanism.
>>>> This is only true when you use select().
>>> Or poll, or epoll, or kqueue (kevent()), or asio (asio_suspend()),
>>> or....
>>>
>>>> You can't make such an
>>>> assumption either because Netty API is not necessarily supposed to use
>>>> selector API only.  For example, a new Netty transport can be
>>>> implemented with old blocking I/O and JDK 7 asynchronous I/O API, and
>>>> therefore it's not a viable option to integrate the timeout feature
>>>> into
>>>> the core out of the box.
>>> With blocking IO, you use a separate thread per blocking event (in this
>>> case, delays) - so again, the callback would not need to fire
>>> recursively in the same call stack.
>>>
>>> I'm unfamiliar with the JDK7 API, but I would be surprised if it did not
>>> have timeouts as well.
>>
>> I agree that select/epoll/... can be used to implement application
>> timeout by specifying poll timeout (Selector.select(long timeout) in
>> Java).
>>
>> JDK 7 AIO allows you to specify read/write timeout, but I'm not sure if
>> it's related with application event timeout scheduling:
>>
>>   * http://tinyurl.com/njh6l6
> 
> Yes, you can simply use the timeout of any single one of the
> asynchronous reads/writes.
> 
>>
>> BTW, I think you are mixing two issues - recursive calls and timeouts.
>> Non-recursive calls can be achieved without timeouts and vice versa.  Is
>> there any reason they need to be implemented in a tightly coupled manner?
> 
> No, and in fact in my original email I did distinguish the two,
> mentioning delays only parenthetically.

Gotcha. :)

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/04fcb9a7/attachment.bin 


More information about the netty-users mailing list