Marc Lehmann wrote:
> Hi!
> On tuesday, I sent mail about various problems with libevent and its
> current API as well as implementation. Unfortunately, the mail has not yet
> shown up, but fortunately, it has been superseded by this one :)
> In that mail, I announced that I will work on the problems I encountered
> in libevent (many of which have been reported and discusssed earlier on
> this list). After analyzing libevent I decided that it wasn't fixable
> except by rewriting the core parts of it (the inability to have multiple
> watchers for the same file descriptor event turned out to be blocking for
> my applications, otherwise I wouldn't have started the effort in the first
> place...).
> The results look promising so far: I additionally implemented a libevent
> compatibility layer and benchmarked both libraries using the benchmark
> program provided by libevent:
> Here is an incomplete list of what I changed and added (see the full
> list at, or the cvs repository at
> fixed or improved:
> * multiple watchers can wait for the same event, there is no limitation
>   to one or two watchers for signals and io.

Could you give me an example of where that is important?

> * there is full support for fork, you can continue to use the event loop
>   in the parent and child (or just one of them), even with quirky backends
>   such as epoll.

Nice; seems like that's come up on the list several times.

> * there are two types of timers, based on real time differences and wall
>   clock time (cron-like). timers can also be repeating and be reset at
>   almost no cost (for idle timeouts used by many network servers). time jumps
>   get detected reliably in both directions with or without a monotonic clock.

(See my other mail about Linux's new timerfd facility.)

Nice; repeating and absolute timers have come up several times before, too.

> * timers are managed by a priority queue (O(1) for important operations
>   as opposed to O(log n) in libevent, also resulting in much simpler code).

In terms of concrete data types, you appear to have used a binary heap?
So by "important operations" you mean removal, correct? Insertion is
still O(log n)? The asymptotic behavior is no different, then, as
insertion happens at least as often as removal.

> * event watchers can be added and removed at any time (in libevent,
>   removing events that are pending can lead to crashes).

(They don't lead to crashes, as someone mentioned.)

> * different types of events use different watchers, so you don't have
>   to use an i/o event watcher for timeouts, and you can reset timers
>   seperately from other types of watchers. Also, watchers are much smaller
>   (even the libevent emulation watcher only has about 2/3 of the size of a
>   libevent watcher).

Nice; separate types can be nice for documentation purposes if nothing else.

> * I added idle watchers, pid watchers and hook watchers into the event loop,
>   as is required for integration of other event-based libraries, without
>   having to force the use of some construct around event_loop.

Pardon my ignorance, but what are hook watchers?

pid watchers I assume to be a fancy SIGCHLD handler? That's a
potentially useful feature, but why would it require a construct around

> * the backends use a much simpler design. unlike in libevent, the code to
>   handle events is not duplicated for each backend, backends deal only
>   with file descriptor events and a single timeout value, everything else
>   is handled by the core, which also optimises state changes (the epoll
>   backend is 100 lines in libev, as opposed to >350 lines in libevent,
>   without suffering from its limitations).


> As for compatibility, the actual libev api is very different to the
> libevent API (although the design is similar), but there is a emulation
> layer with a corresponding event.h file that supports the event library
> (but no evbuffer, evnds, evhttp etc.).

I think the API needs more hashing out. It is...different...but I'm not
sure it's necessarily better, and I don't like change for change's sake.
A few notes:

* what is the purpose of EV_COMMON? From first glance, I'm concerned
that it could not be used properly unless and all callers are
compiled with the same flags, which seems impractical if the library
ever gains wide use.

* on ev_once failure, you're calling the callback with EV_ERROR? Yuck.
That's quite surprising behavior, and I could see it leading to stack
overflows as each ev_once tries to issue another one.

* What's your use case for ev_loop_new() and ev_loop_default()'s bitmask
of allowed implementations?

* (again, just skimming) you're closing fds automatically on ENOMEM?
Ergh. That seems rather undesirable for many applications.

Libevent-users mailing list

Reply via email to