39
|
1 |
from qmsk.net.lib.event2.base cimport *
|
|
2 |
from qmsk.net.lib.event2.event cimport build_timeout
|
|
3 |
|
41
|
4 |
class EventError (Exception) :
|
|
5 |
"""
|
|
6 |
Base class of errors raised by lib.event2 code
|
|
7 |
"""
|
|
8 |
|
|
9 |
pass
|
|
10 |
|
|
11 |
class EventCallError (EventError) :
|
|
12 |
"""
|
|
13 |
Some libevent function returned an error code.
|
|
14 |
"""
|
|
15 |
|
|
16 |
def __init__ (self, func, msg=None) :
|
|
17 |
super(EventCallError, self).__init__(func)
|
|
18 |
|
|
19 |
self.func = func
|
|
20 |
self.msg = msg
|
|
21 |
|
39
|
22 |
cdef class event_base :
|
|
23 |
|
|
24 |
def __init__ (self) :
|
|
25 |
|
|
26 |
# construct
|
|
27 |
self.ev_base = lib.event_base_new()
|
|
28 |
|
|
29 |
if self.ev_base == NULL :
|
41
|
30 |
raise EventCallError("event_base_new")
|
39
|
31 |
|
|
32 |
def reinit (self) :
|
|
33 |
"""
|
|
34 |
Re-initialize the event_base following a fork(). This is required for some event mechanisms.
|
|
35 |
|
|
36 |
Raises an error if some events could not be re-added.
|
|
37 |
"""
|
|
38 |
|
|
39 |
if lib.event_reinit(self.ev_base) < 0 :
|
41
|
40 |
raise EventCallError("event_reinit", "could not re-add all events")
|
39
|
41 |
|
|
42 |
property method :
|
|
43 |
def __get__ (self) :
|
|
44 |
"""
|
|
45 |
Query the underlying method used by this event_base as a string ("kqueue", "epoll", etc.)
|
|
46 |
"""
|
|
47 |
|
|
48 |
return lib.event_base_get_method(self.ev_base)
|
|
49 |
|
|
50 |
def loop (self, once = False, nonblock = False) :
|
|
51 |
"""
|
|
52 |
Run the event loop.
|
|
53 |
|
|
54 |
once - only run the event loop once, at most
|
|
55 |
nonblock - do not block waiting for events
|
41
|
56 |
|
|
57 |
Returns True if succesfull, False if no events were registered
|
39
|
58 |
"""
|
|
59 |
|
|
60 |
cdef int flags = 0
|
|
61 |
|
|
62 |
# build flags
|
|
63 |
if once :
|
|
64 |
flags |= lib.EVLOOP_ONCE
|
|
65 |
|
|
66 |
if nonblock :
|
|
67 |
flags |= lib.EVLOOP_NONBLOCK
|
|
68 |
|
|
69 |
# event_base_loop()
|
41
|
70 |
ret = lib.event_base_loop(self.ev_base, flags)
|
|
71 |
|
|
72 |
if ret < 0 :
|
|
73 |
raise EventCallError("event_base_loop")
|
|
74 |
|
|
75 |
elif ret > 0 :
|
|
76 |
return False
|
|
77 |
|
|
78 |
else :
|
|
79 |
return True
|
39
|
80 |
|
|
81 |
def loopexit (self, timeout = None) :
|
|
82 |
"""
|
|
83 |
Exit the event loop normally.
|
|
84 |
|
|
85 |
This will optionally wait until the given timeout expires, and then allow the current event loop iteration
|
|
86 |
to complete normally, before causing .loop() to return.
|
|
87 |
"""
|
|
88 |
|
|
89 |
cdef lib.timeval tv
|
|
90 |
|
|
91 |
if lib.event_base_loopexit(self.ev_base, build_timeout(&tv, timeout)) < 0 :
|
41
|
92 |
raise EventCallError("event_base_loopexit")
|
39
|
93 |
|
|
94 |
def loopbreak (self) :
|
|
95 |
"""
|
|
96 |
Abort the event immediately.
|
|
97 |
|
|
98 |
The current event loop will end and .loop() return as soon as the currently running event has been
|
|
99 |
processed.
|
|
100 |
"""
|
|
101 |
|
|
102 |
if lib.event_base_loopbreak(self.ev_base) < 0 :
|
41
|
103 |
raise EventCallError("event_base_loopbreak")
|
39
|
104 |
|
|
105 |
def __dealloc__ (self) :
|
|
106 |
"""
|
|
107 |
Release the event_base's resources.
|
|
108 |
|
|
109 |
XXX: is this entirely safe re our events?
|
|
110 |
"""
|
|
111 |
|
|
112 |
lib.event_base_free(self.ev_base)
|
|
113 |
|