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

The results look promising so far: I additionally implemented a libevent
compatibility layer and benchmarked both libraries using the benchmark
program provided by libevent: http://libev.schmorp.de/bench.html

Here is an incomplete list of what I changed and added (see the full
list at http://cvs.schmorp.de/libev/README, 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.

* 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.

* 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.

* 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).

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

* 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).

* 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.

* 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.).

It works very well: both the testsuite as well as the benchmark program from
libevent work as expected, and the evdns code compiles (and runs) without any
changes, making libev a drop-in replacement for libevent users. "Porting"
evbuffer and so on would be equally trivial.

However: libev has not yet been released on its own (only as part of
the EV perl module), meaning there is no configure script, C-level
documentation etc.

The "obvious" plan would be to take the evhttp etc. code from libevent and
paste it in to libev, making libev a complete replacement for libevent
with an optional new API. The catch is, I'd like to avoid this, because I
am not prepared to maintain yet another library, and I am not keen on
replicating the configure and portability work that went into libevent so

So, would there be an interest in replacing the "core" event part of
libevent with the libev code? If yes, there are a number of issues to
solve, and here is how I would solve them:

* libev only supports select and epoll. Adding poll would be trivial for me,
  and adding dev/poll and kqueue support would be easy, except that I don't
  want to set-up some bsd machines just for that. I would, however, opt to
  write kqueue and /dev/poll backends "dry" and let somebody else do the
  actual porting stuff to the then-existing backends.

* libev only supports one "event base". The reason is that I think a
  leader/ follower pattern together with lazy I/O would beat any multiple
  event loop implementation, and the fact that each time I see some
  software module using its own copy of some mainloop meant that it
  doesn't work together with other such modules :) Still, if integration
  should be achieved, this is no insurmountable obstacle :->

* libev uses its own api, which potentially causes some global symbol
  spamming (lots of functions with ev_ prefix). This could be used as a
  chance to switch to a more efficient API while at the same time keeping
  100% backwards compatibility. (The event emulation layer in libev is
  only 1.3kb of codesize on my machine, so reasonably thin).

So what do you think? If you are not interested, I am prepared to maintain
it on my own, too, so there is no pressure for either direction, I think.

Greetings, and thanke for making me write my own event loop something I
had planned to do for many years now :) Also kudos for the event_once
interface, which I hadn't implemented if I hadn't seen it in libevent

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      [EMAIL PROTECTED]
      -=====/_/_//_/\_,_/ /_/\_\
Libevent-users mailing list

Reply via email to