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

Re: [Libevent-users] event_base_loop: wait for events to be added by other threads?



On Fri, Dec 3, 2010 at 3:20 PM, Evan Jones <evanj@xxxxxxx> wrote:
> I am writing a multi-threaded libevent application. Or rather, I am
> retrofitting an existing libevent 1.4 application to contain multiple
> libevent threads. Since the existing code is NOT thread safe, my design is
> basically to partition the application into N pieces, each with its own
> event loop. Then I glue the pieces together by scheduling callbacks in
> appropriate threads using event_active.

A quick heads-up here that you'll want to know: there's a bug in
2.0.9-rc and earlier where activating an event from another thread
doesn't wake up the loop immediately.  It should be fixed in 2.0.10;
see commit 5beeec9d43cb.

> There is one small problem: if a thread has no active events, it exits. In
> my case, I want it to block, waiting for another thread to call event_active
> to add an event. I have a patch to libevent that fixes this by adding an
> additional flag to event_base_loop. Is this the "right" solution to this
> problem?

Wow, good timing.  I actually coded up an example patch to try to do
this earlier this week; have a look at branch "21_evloop_emptyok" in
my github repository [git://github.com/nmathewson/Libevent.git] and
see if it looks okay to you.  I don't like the EMPTYOK name, but the
rest of it seemed ok.

Since 2.0 is in feature-freeze, this can't go in until we fork 2.1.x,
of course.  As an (admittedly ugly) workaround for 2.0, you can just
add a periodic timeout event with a very high timeout and a callback
that does nothing.  It's not a great solution, but it will work for
now.

> If so, I have another concern: the three current flags to libevent are
> actually mutually exclusive. Eg. If you pass EVLOOP_NONBLOCK, that sort of
> implies EVLOOP_ONCE. Similarly, my new flag is incompatible with
> EVLOOP_NONBLOCK and EVLOOP_ONCE. Does it make sense to assign each one a
> bit? Or should the first two bits of flag be the "loop mode"?
>
> 00 = normal; run until no active events
> 01 = EVLOOP_ONCE; wait until one event is triggered then exit
> 10 = EVLOOP_NONBLOCK; poll the loop once, run highest priority, then exit
> 11 = EVLOOP_BLOCK_FOR_EXPLICIT_EXIT; run until there is an explicit exit.

As I construe it, these aren't mutually exclusive in quite that way.
The normal behavior is, in theory:

  while (events are pending) {
      wait for events to be active;
      run callbacks all active events at the highest priority
  }

But the real behavior, from event_base_loop, with these flags taken
into account, is more or less:

  while (events are pending ||  EMPTYOK/EXPLICIT_EXIT is set) {
      if (NONBLOCK is set or there are active callbacks)
         check if events are active, but do not wait.
      else
         wait for events to become active

      if (we have active callbacks) {
         run callbacks for active events at the highest priority
         if (ONCE &&
            we had active, non-internal callbacks &&
            we have no more active callbacks)
           break;
      } else if (NONBLOCK is set) {
        break;
      }
   }

So let's see:
ONCE means wait till at least one non-internal callback is activated,
then to run until there are no active callbacks.
EMPTYOK|ONCE means wait till at least one non-internal callback is
activated, then to run until there are no active callbacks, EVEN IF we
didn't start with any pending events.
NONBLOCK means to check events and run user callbacks until no more
pending events want to be activated.
EMPTYOK|NONBLOCK means to check events and run user callbacks until no
more pending events want to be activated, EVEN IF we didn't start with
any pending events.
ONCE|NONBLOCK doesn't seem reasonable to me atm.

So I'm okay with having all three be flags.

yrs,
-- 
Nick
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.