Commit cdc1d6dd authored by Jason Madden's avatar Jason Madden

Start breaking apart the WATCHER macro to share code.

Move to the safer __cinit__ for all watchers.

Now that the base watcher has access to its libev ev_watcher pointer, start moving the properties there, starting with ref.
parent 045afd00
...@@ -179,11 +179,16 @@ static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallback ...@@ -179,11 +179,16 @@ static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallback
Py_DECREF(loop); Py_DECREF(loop);
} }
/*
* PyGeventWatcherObject is the first member of all the structs, so
* it is the same in all of them and they can all safely be cast to
* it. We could also use the *data member of the libev watcher objects.
*/
#undef DEFINE_CALLBACK #undef DEFINE_CALLBACK
#define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \ #define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \
static void gevent_callback_##WATCHER_LC(struct ev_loop *_loop, void *c_watcher, int revents) { \ static void gevent_callback_##WATCHER_LC(struct ev_loop *_loop, void *c_watcher, int revents) { \
struct PyGevent##WATCHER_TYPE##Object* watcher = GET_OBJECT(PyGevent##WATCHER_TYPE##Object, c_watcher, _watcher); \ struct PyGeventWatcherObject* watcher = GET_OBJECT(PyGevent##WATCHER_TYPE##Object, c_watcher, _watcher); \
gevent_callback(watcher->loop, watcher->_callback, watcher->args, (PyObject*)watcher, c_watcher, revents); \ gevent_callback(watcher->loop, watcher->_callback, watcher->args, (PyObject*)watcher, c_watcher, revents); \
} }
......
...@@ -666,32 +666,8 @@ cdef public class callback [object PyGeventCallbackObject, type PyGeventCallback ...@@ -666,32 +666,8 @@ cdef public class callback [object PyGeventCallbackObject, type PyGeventCallback
# bit #3 set if user wants to call ev_unref() before start() # bit #3 set if user wants to call ev_unref() before start()
#define WATCHER_BASE(TYPE) \ #define WATCHER_BASE(TYPE) \
cdef public loop loop \
cdef object _callback \
cdef public tuple args \
cdef readonly int _flags \
cdef libev.ev_##TYPE _watcher \ cdef libev.ev_##TYPE _watcher \
\ \
@property \
def ref(self): \
return False if self._flags & 4 else True \
\
@ref.setter \
def ref(self, object value): \
_check_loop(self.loop) \
if value: \
if not self._flags & 4: \
return # ref is already True \
if self._flags & 2: # ev_unref was called, undo \
libev.ev_ref(self.loop._ptr) \
self._flags &= ~6 # do not want unref, no outstanding unref \
else: \
if self._flags & 4: \
return # ref is already False \
self._flags |= 4 \
if not self._flags & 2 and libev.ev_is_active(&self._watcher): \
libev.ev_unref(self.loop._ptr) \
self._flags |= 2 \
\ \
@property \ @property \
def callback(self): \ def callback(self): \
...@@ -768,20 +744,46 @@ cdef public class callback [object PyGeventCallbackObject, type PyGeventCallback ...@@ -768,20 +744,46 @@ cdef public class callback [object PyGeventCallbackObject, type PyGeventCallback
#define COMMA , #define COMMA ,
#define INIT(TYPE, ARGS_INITIALIZERS, ARGS) \
def __init__(self, loop loop ARGS_INITIALIZERS, ref=True, priority=None): \
libev.ev_##TYPE##_init(&self._watcher, <void *>gevent_callback_##TYPE ARGS) \
self.loop = loop \
if ref: \
self._flags = 0 \
else: \
self._flags = 4 \
if priority is not None: \
libev.ev_set_priority(&self._watcher, priority)
cdef public class watcher [object PyGeventWatcherObject, type PyGeventWatcher_Type]: cdef public class watcher [object PyGeventWatcherObject, type PyGeventWatcher_Type]:
"""Abstract base class for all the watchers""" """Abstract base class for all the watchers"""
cdef public loop loop
cdef object _callback
cdef public tuple args
cdef readonly int _flags
cdef libev.ev_watcher* __watcher
def __init__(self, loop loop, ref=True, priority=None):
if not self.__watcher:
raise ValueError("Cannot construct a bare watcher")
self.loop = loop
if ref:
self._flags = 0
else:
self._flags = 4
if priority is not None:
libev.ev_set_priority(self.__watcher, priority)
@property
def ref(self):
return False if self._flags & 4 else True
@ref.setter
def ref(self, object value):
_check_loop(self.loop)
if value:
if not self._flags & 4:
return # ref is already True
if self._flags & 2: # ev_unref was called, undo
libev.ev_ref(self.loop._ptr)
self._flags &= ~6 # do not want unref, no outstanding unref
else:
if self._flags & 4:
return # ref is already False
self._flags |= 4
if not self._flags & 2 and libev.ev_is_active(self.__watcher):
libev.ev_unref(self.loop._ptr)
self._flags |= 2
def __repr__(self): def __repr__(self):
if Py_ReprEnter(<PyObjectPtr>self) != 0: if Py_ReprEnter(<PyObjectPtr>self) != 0:
...@@ -836,41 +838,36 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]: ...@@ -836,41 +838,36 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]:
PENDING PENDING
cpdef __posix_cinit(self, loop loop, int fd, int events, ref=True, priority=None):
if fd < 0:
raise ValueError('fd must be non-negative: %r' % fd)
if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE):
raise ValueError('illegal event mask: %r' % events)
libev.ev_io_init(&self._watcher, <void *>gevent_callback_io, fd, events)
self.__watcher = <libev.ev_watcher*>&self._watcher
#ifdef _WIN32 #ifdef _WIN32
def __init__(self, loop loop, libev.vfd_socket_t fd, int events, ref=True, priority=None): def __cinit__(self, loop loop, libev.vfd_socket_t fd, int events, ref=True, priority=None):
if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE): if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE):
raise ValueError('illegal event mask: %r' % events) raise ValueError('illegal event mask: %r' % events)
cdef int vfd = libev.vfd_open(fd) cdef int vfd = libev.vfd_open(fd)
libev.vfd_free(self._watcher.fd) self.__posix_cinit(loop, vfd, events, ref, priority)
libev.ev_io_init(&self._watcher, <void *>gevent_callback_io, vfd, events)
self.loop = loop
if ref:
self._flags = 0
else:
self._flags = 4
if priority is not None:
libev.ev_set_priority(&self._watcher, priority)
#else def __init__(self, loop loop, libev.vfd_socket_t fd, int events, ref=True, priority=None):
watcher.__init__(self, loop, ref, priority)
def __init__(self, loop loop, int fd, int events, ref=True, priority=None): def __dealloc__(self):
if fd < 0: libev.vfd_free(self._watcher.fd)
raise ValueError('fd must be non-negative: %r' % fd)
if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE): # cythonpp can produce code that cannot compile if the same methods are
raise ValueError('illegal event mask: %r' % events) # defined in blocks too close together. So the POSIX version of this
libev.ev_io_init(&self._watcher, <void *>gevent_callback_io, fd, events) # has to be defined several methods down.
self.loop = loop
if ref:
self._flags = 0
else:
self._flags = 4
if priority is not None:
libev.ev_set_priority(&self._watcher, priority)
#endif #endif
@property @property
def fd(self): def fd(self):
return libev.vfd_get(self._watcher.fd) return libev.vfd_get(self._watcher.fd)
...@@ -901,16 +898,20 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]: ...@@ -901,16 +898,20 @@ cdef public class io(watcher) [object PyGeventIOObject, type PyGeventIO_Type]:
return ' fd=%s events=%s' % (self.fd, self.events_str) return ' fd=%s events=%s' % (self.fd, self.events_str)
#ifdef _WIN32 #ifdef _WIN32
#else
def __cinit__(self): def __cinit__(self, loop loop, int fd, int events, ref=True, priority=None):
self._watcher.fd = -1; self.__posix_cinit(loop, fd, events, ref, priority)
def __init__(self, loop loop, int fd, int events, ref=True, priority=None):
watcher.__init__(self, loop, ref, priority)
def __dealloc__(self):
libev.vfd_free(self._watcher.fd)
#endif #endif
cdef public class timer(watcher) [object PyGeventTimerObject, type PyGeventTimer_Type]: cdef public class timer(watcher) [object PyGeventTimerObject, type PyGeventTimer_Type]:
WATCHER_BASE(timer) WATCHER_BASE(timer)
...@@ -935,17 +936,14 @@ cdef public class timer(watcher) [object PyGeventTimerObject, type PyGeventTimer ...@@ -935,17 +936,14 @@ cdef public class timer(watcher) [object PyGeventTimerObject, type PyGeventTimer
PENDING PENDING
def __init__(self, loop loop, double after=0.0, double repeat=0.0, ref=True, priority=None): def __cinit__(self, loop loop, double after=0.0, double repeat=0.0, ref=True, priority=None):
if repeat < 0.0: if repeat < 0.0:
raise ValueError("repeat must be positive or zero: %r" % repeat) raise ValueError("repeat must be positive or zero: %r" % repeat)
libev.ev_timer_init(&self._watcher, <void *>gevent_callback_timer, after, repeat) libev.ev_timer_init(&self._watcher, <void *>gevent_callback_timer, after, repeat)
self.loop = loop self.__watcher = <libev.ev_watcher*>&self._watcher
if ref:
self._flags = 0 def __init__(self, loop loop, double after=0.0, double repeat=0.0, ref=True, priority=None):
else: watcher.__init__(self, loop, ref, priority)
self._flags = 4
if priority is not None:
libev.ev_set_priority(&self._watcher, priority)
@property @property
def at(self): def at(self):
...@@ -968,7 +966,7 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig ...@@ -968,7 +966,7 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig
WATCHER(signal) WATCHER(signal)
def __init__(self, loop loop, int signalnum, ref=True, priority=None): def __cinit__(self, loop loop, int signalnum, ref=True, priority=None):
if signalnum < 1 or signalnum >= signalmodule.NSIG: if signalnum < 1 or signalnum >= signalmodule.NSIG:
raise ValueError('illegal signal number: %r' % signalnum) raise ValueError('illegal signal number: %r' % signalnum)
# still possible to crash on one of libev's asserts: # still possible to crash on one of libev's asserts:
...@@ -977,41 +975,47 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig ...@@ -977,41 +975,47 @@ cdef public class signal(watcher) [object PyGeventSignalObject, type PyGeventSig
# 2) "libev: a signal must not be attached to two different loops" # 2) "libev: a signal must not be attached to two different loops"
# we probably could check that in LIBEV_EMBED mode, but not in general # we probably could check that in LIBEV_EMBED mode, but not in general
libev.ev_signal_init(&self._watcher, <void *>gevent_callback_signal, signalnum) libev.ev_signal_init(&self._watcher, <void *>gevent_callback_signal, signalnum)
self.loop = loop self.__watcher = <libev.ev_watcher*>&self._watcher
if ref:
self._flags = 0 def __init__(self, loop loop, int signalnum, ref=True, priority=None):
else: watcher.__init__(self, loop, ref, priority)
self._flags = 4
if priority is not None:
libev.ev_set_priority(&self._watcher, priority)
cdef public class idle(watcher) [object PyGeventIdleObject, type PyGeventIdle_Type]: cdef public class idle(watcher) [object PyGeventIdleObject, type PyGeventIdle_Type]:
WATCHER(idle) WATCHER(idle)
INIT(idle,,) def __cinit__(self, loop loop, ref=True, priority=None):
libev.ev_idle_init(&self._watcher, <void*>gevent_callback_idle)
self.__watcher = <libev.ev_watcher*>&self._watcher
cdef public class prepare(watcher) [object PyGeventPrepareObject, type PyGeventPrepare_Type]: cdef public class prepare(watcher) [object PyGeventPrepareObject, type PyGeventPrepare_Type]:
WATCHER(prepare) WATCHER(prepare)
INIT(prepare,,) def __cinit__(self, loop loop, ref=True, priority=None):
libev.ev_prepare_init(&self._watcher, <void*>gevent_callback_prepare)
self.__watcher = <libev.ev_watcher*>&self._watcher
cdef public class check(watcher) [object PyGeventCheckObject, type PyGeventCheck_Type]: cdef public class check(watcher) [object PyGeventCheckObject, type PyGeventCheck_Type]:
WATCHER(check) WATCHER(check)
INIT(check,,) def __cinit__(self, loop loop, ref=True, priority=None):
libev.ev_check_init(&self._watcher, <void*>gevent_callback_check)
self.__watcher = <libev.ev_watcher*>&self._watcher
cdef public class fork(watcher) [object PyGeventForkObject, type PyGeventFork_Type]: cdef public class fork(watcher) [object PyGeventForkObject, type PyGeventFork_Type]:
WATCHER(fork) WATCHER(fork)
INIT(fork,,) def __cinit__(self, loop loop, ref=True, priority=None):
libev.ev_fork_init(&self._watcher, <void*>gevent_callback_fork)
self.__watcher = <libev.ev_watcher*>&self._watcher
cdef public class async_(watcher) [object PyGeventAsyncObject, type PyGeventAsync_Type]: cdef public class async_(watcher) [object PyGeventAsyncObject, type PyGeventAsync_Type]:
...@@ -1027,7 +1031,9 @@ cdef public class async_(watcher) [object PyGeventAsyncObject, type PyGeventAsyn ...@@ -1027,7 +1031,9 @@ cdef public class async_(watcher) [object PyGeventAsyncObject, type PyGeventAsyn
# Note the use of ev_async_pending instead of ev_is_pending # Note the use of ev_async_pending instead of ev_is_pending
return True if libev.ev_async_pending(&self._watcher) else False return True if libev.ev_async_pending(&self._watcher) else False
INIT(async,,) def __cinit__(self, loop loop, ref=True, priority=None):
libev.ev_async_init(&self._watcher, <void*>gevent_callback_async)
self.__watcher = <libev.ev_watcher*>&self._watcher
def send(self): def send(self):
_check_loop(self.loop) _check_loop(self.loop)
...@@ -1042,16 +1048,15 @@ cdef public class child(watcher) [object PyGeventChildObject, type PyGeventChild ...@@ -1042,16 +1048,15 @@ cdef public class child(watcher) [object PyGeventChildObject, type PyGeventChild
WATCHER(child) WATCHER(child)
def __init__(self, loop loop, int pid, bint trace=0, ref=True): def __cinit__(self, loop loop, int pid, bint trace=0, ref=True):
if not loop.default: if not loop.default:
raise TypeError('child watchers are only available on the default loop') raise TypeError('child watchers are only available on the default loop')
libev.gevent_install_sigchld_handler() libev.gevent_install_sigchld_handler()
libev.ev_child_init(&self._watcher, <void *>gevent_callback_child, pid, trace) libev.ev_child_init(&self._watcher, <void *>gevent_callback_child, pid, trace)
self.loop = loop self.__watcher = <libev.ev_watcher*>&self._watcher
if ref:
self._flags = 0 def __init__(self, loop loop, int pid, bint trace=0, ref=True):
else: watcher.__init__(self, loop, ref, None)
self._flags = 4
def _format(self): def _format(self):
return ' pid=%r rstatus=%r' % (self.pid, self.rstatus) return ' pid=%r rstatus=%r' % (self.pid, self.rstatus)
...@@ -1085,7 +1090,7 @@ cdef public class stat(watcher) [object PyGeventStatObject, type PyGeventStat_Ty ...@@ -1085,7 +1090,7 @@ cdef public class stat(watcher) [object PyGeventStatObject, type PyGeventStat_Ty
cdef readonly str path cdef readonly str path
cdef readonly bytes _paths cdef readonly bytes _paths
def __init__(self, loop loop, str path, float interval=0.0, ref=True, priority=None): def __cinit__(self, loop loop, str path, float interval=0.0, ref=True, priority=None):
self.path = path self.path = path
cdef bytes paths cdef bytes paths
if isinstance(path, unicode): if isinstance(path, unicode):
...@@ -1098,13 +1103,10 @@ cdef public class stat(watcher) [object PyGeventStatObject, type PyGeventStat_Ty ...@@ -1098,13 +1103,10 @@ cdef public class stat(watcher) [object PyGeventStatObject, type PyGeventStat_Ty
paths = <bytes>path paths = <bytes>path
self._paths = paths self._paths = paths
libev.ev_stat_init(&self._watcher, <void *>gevent_callback_stat, <char*>paths, interval) libev.ev_stat_init(&self._watcher, <void *>gevent_callback_stat, <char*>paths, interval)
self.loop = loop self.__watcher = <libev.ev_watcher*>&self._watcher
if ref:
self._flags = 0 def __init__(self, loop loop, str path, float interval=0.0, ref=True, priority=None):
else: watcher.__init__(self, loop, ref, priority)
self._flags = 4
if priority is not None:
libev.ev_set_priority(&self._watcher, priority)
@property @property
def attr(self): def attr(self):
......
...@@ -87,6 +87,9 @@ cdef extern from "libev.h": ...@@ -87,6 +87,9 @@ cdef extern from "libev.h":
int sigfd int sigfd
unsigned int origflags unsigned int origflags
struct ev_watcher:
void* data;
struct ev_io: struct ev_io:
int fd int fd
int events int events
......
...@@ -15,6 +15,7 @@ import subprocess ...@@ -15,6 +15,7 @@ import subprocess
import multiprocessing import multiprocessing
import tempfile import tempfile
import shutil import shutil
from collections import OrderedDict
import threading import threading
...@@ -376,7 +377,7 @@ class ConfigurationGroups(tuple): ...@@ -376,7 +377,7 @@ class ConfigurationGroups(tuple):
if self._simplified: if self._simplified:
return self return self
for tag1, tag2 in combinations(self, 2): for tag1, tag2 in sorted(combinations(self, 2)):
if tag1 == tag2: if tag1 == tag2:
tags = list(self) tags = list(self)
tags.remove(tag1) tags.remove(tag1)
...@@ -555,7 +556,7 @@ def preprocess_filename(filename, config): ...@@ -555,7 +556,7 @@ def preprocess_filename(filename, config):
""" """
linecount = 0 linecount = 0
current_name = None current_name = None
definitions = {} definitions = OrderedDict()
result = [] result = []
including_section = [] including_section = []
with open(filename) as f: with open(filename) as f:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment