# HG changeset patch # User Tero Marttila # Date 1253991042 -10800 # Node ID 722fc70a197abe0ff6d28686880dd7a8a51fe470 # Parent c6b4abfc21da7b09d7e97835a7711fae5df2a8cc change CallbackEvent to replace fd with ev, event2 doc/style tweaks diff -r c6b4abfc21da -r 722fc70a197a qmsk/net/lib/event2/base.pxd --- a/qmsk/net/lib/event2/base.pxd Sat Sep 26 21:46:36 2009 +0300 +++ b/qmsk/net/lib/event2/base.pxd Sat Sep 26 21:50:42 2009 +0300 @@ -11,10 +11,39 @@ Constructs a new event_base with default parameters. + XXX: you must keep a reference to the event_base around yourself! + XXX: what happens to events once we are destructed? + + Libevent has its own asynchronous signal-handling mechanism that is incompatible with Python's signal-handling + mechanism. + + Technical details: + Python's signal handlers will simply set a flag corresponding to the signal, and wait for + PyErr_CheckSignals to be run. Following this, libevent's epoll/select/etc() call will return EINTER - but + this will only cause libevent to check its own signal state, and continue running. + + To solve this, we register a "wakeup fd" in Python's signal handling system, whereby a byte is written to a + socket pair whenever python's signal handler runs. We then register an (internal) event for the other end of + this socketpair in the event_base, which then runs the python signal handlers from "inside" of .loop(), + propagating exceptions out of .loop() - this solution is more or less equivalent to how libevent's signal + handling works. + + This means that python's default signals and any other signals added using the signal module continue to work + at the cost of some additional complexity, but any libevent signal-events also work as well :) + + XXX: currently, you can only have one event_base at a time - there should be separate types used for the main + thread and sub-threads, since the python signal handling mechanism only works in the main thread. + + XXX: the propagate-exceptions doesn't actually work either, it just aborts the event loop :) + XXX: add support for event_config! XXX: add support for event_base_priority_init! + """ # the underlying ev_base object cdef lib.event_base *ev_base + # internal event for PySignal wakeups + cdef lib.event *ev_pysignal + diff -r c6b4abfc21da -r 722fc70a197a qmsk/net/lib/event2/event.pxd --- a/qmsk/net/lib/event2/event.pxd Sat Sep 26 21:46:36 2009 +0300 +++ b/qmsk/net/lib/event2/event.pxd Sat Sep 26 21:50:42 2009 +0300 @@ -25,6 +25,11 @@ The lifetime of event objects is slightly non-trivial, in that they will actually hold a reference to themselves while "active". In other words, .add() will aquire an internal reference, which will be released before the __call__(). + + XXX: it might be better for refcounting if the event_base were to keep a reference to each event + XXX: or if we kept a reference to the event_base? Might be even better + + XXX: propagate errors (including e.g. KeyboardInterrupt?) from __call__ to event_base.loop()? """ # the underlying event object diff -r c6b4abfc21da -r 722fc70a197a qmsk/net/lib/event2/event.pyx --- a/qmsk/net/lib/event2/event.pyx Sat Sep 26 21:46:36 2009 +0300 +++ b/qmsk/net/lib/event2/event.pyx Sat Sep 26 21:50:42 2009 +0300 @@ -53,7 +53,7 @@ raise ValueError(fd) # construct event using our internal callback, with self as the arg - self.ev = lib.event_new(base.ev_base, fd, events, ev_callback, self) + self.ev = lib.event_new(base.ev_base, fd, events, ev_callback, self) if self.ev == NULL : raise Exception("event_new") @@ -70,7 +70,7 @@ raise RuntimeError("Cannot change event while active") # interesting... no error return code - lib.event_assign(self.ev, base.ev_base, fd, events, ev_callback, self) + lib.event_assign(self.ev, base.ev_base, fd, events, ev_callback, self) def add (self, timeout = None) : @@ -197,6 +197,8 @@ class CallbackEvent (event) : """ Extends the event type to take a callback and additional arguments to invoke from the __call__ method. + + This will pass the event object itself to the callback in place of the fd. """ def __init__ (self, event_base base, lib.evutil_socket_t fd, short events, object callback, *args, **kwargs) : @@ -209,5 +211,5 @@ self.kwargs = kwargs def __call__ (self, lib.evutil_socket_t fd, short mask) : - self.callback(fd, mask, *self.args, **self.kwargs) + self.callback(self, mask, *self.args, **self.kwargs)