[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] Using event_active() for partial reading with bufferevents





On Tue, Nov 6, 2012 at 7:37 AM, Nick Mathewson <nickm@xxxxxxxxxxxxx> wrote:

On Tue, Nov 6, 2012 at 12:29 AM, Himanshu S <mail2himanshu@xxxxxxxxx> wrote:
Hi,
   I am using bufferevent_* APIs for my application to read/write data to TCP stream. When the data arrives, the read callback happens, I want to read partial data (at times), and then be able to post an event back so that the event is queued up and read callback is called again. I thought event_active() gives this functionality but apparently its not. I am using event_active with following parameters,

event_active(&bev->ev_read, EV_READ, 1);

That is _really_ not supported. Anything that touches bufferevent internals is going to get you potentially unpredicted results.  

Nick, Thanks for the quick response & help. Yes, I understand that correct way of doing this would be to have an API in bufferevent & taking BEV_LOCK().

Right now the best way to do what you have in mind is to consider *why* you only want to read partial data and then read again after the next event loop -- there's usually a better way to do whatever you're trying to achieve.

The main reason for doing this is to avoid spending unfair amount of time on a single stream.
 
 But if there isn't, and you want to make sure your code works with future versions of Libevent, your best bet is either to add a feature like this in Libevent 2.1, or to create a separate event whose callback will also run the bufferevent's callback, and activate that one.

Is it true that the event_active() works only from a different thread? I see event_active() eventually calls event_callback_activate_nolock_() & it checks if the thread_id is different. So event if I create a separate event & call event_active() on that event, from the same thread, would it still work?

int
event_callback_activate_nolock_(struct event_base *base,
    struct event_callback *evcb)
{
 
...

    event_queue_insert_active(base, evcb);

    if (EVBASE_NEED_NOTIFY(base)) <-----
        evthread_notify_base(base);

    return r;
}

#define EVBASE_NEED_NOTIFY(base)             \
    (evthread_id_fn_ != NULL &&             \
        (base)->running_loop &&             \
        (base)->th_owner_id != evthread_id_fn_()) <----


Again, Thanks for your help.



hth,
-- 
Nick