Events

Yang Zhang yanghatespam at gmail.com
Mon Jun 8 03:28:05 EDT 2009


이희승 (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.

Another example:

   class Thing {
     synchronized public void foo() {
       Callback callback = new Callback() {
         public void callback(Result x) {
           synchronized(object) { Thing.this.handle(x); }
         }
       };
       doSomethingAsynchronous(..., callback);
     }
     synchronized public void handle(Result r) { ... }
   }

The innocuous attempt to synchronize (serialize) accesses to the Thing 
lead this fragment to halt, given the current framework semantics.

> 
>>>> 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.
-- 
Yang Zhang
http://www.mit.edu/~y_z/



More information about the netty-users mailing list