diff --git a/src/gevent/_ffi/watcher.py b/src/gevent/_ffi/watcher.py index 76bbcdc511c3461230dd5712154300c0cac5a9ab..44d6353adb0abd32e1f8a2c55de6b28705c65ae1 100644 --- a/src/gevent/_ffi/watcher.py +++ b/src/gevent/_ffi/watcher.py @@ -57,13 +57,14 @@ class AbstractWatcherType(type): @classmethod def _fill_watcher(cls, name, bases, cls_dict): - def _mro_get(attr, bases): + def _mro_get(attr, bases, error=True): for b in bases: try: return getattr(b, attr) except AttributeError: continue - raise AttributeError(attr) + if error: + raise AttributeError(attr) _watcher_prefix = cls_dict.get('_watcher_prefix') or _mro_get('_watcher_prefix', bases) if '_watcher_type' not in cls_dict: @@ -80,12 +81,19 @@ class AbstractWatcherType(type): LazyOnClass.lazy(cls_dict, _watcher_is_active) + watcher_struct_pattern = (cls_dict.get('_watcher_struct_pattern') + or _mro_get('_watcher_struct_pattern', bases, False) + or 'struct %s') + watcher_struct_name = watcher_struct_pattern % (watcher_type,) + def _watcher_struct_pointer_type(self): - return self._FFI.typeof('struct ' + self._watcher_type + '*') + return self._FFI.typeof(watcher_struct_name + ' *') LazyOnClass.lazy(cls_dict, _watcher_struct_pointer_type) - callback_name = cls_dict.get('watcher_callback_name', '_gevent_generic_callback') + callback_name = (cls_dict.get('_watcher_callback_name') + or _mro_get('_watcher_callback_name', bases, False) + or '_gevent_generic_callback') def _watcher_callback(self): return self._FFI.addressof(self._LIB, callback_name) @@ -147,6 +155,9 @@ class watcher(object): def _watcher_ffi_start(self): raise NotImplementedError() + def _watcher_ffi_stop(self): + self._watcher_stop(self.loop._ptr, self._watcher) + def _watcher_ffi_ref(self): raise NotImplementedError() @@ -238,7 +249,7 @@ class watcher(object): def stop(self): self._watcher_ffi_ref() - self._watcher_stop(self.loop._ptr, self._watcher) + self._watcher_ffi_stop() self.loop._keepaliveset.discard(self) self.callback = None @@ -263,18 +274,29 @@ class watcher(object): watcher = AbstractWatcherType('watcher', (object,), dict(watcher.__dict__)) +import functools + +def not_while_active(func): + @functools.wraps(func) + def nw(self, *args, **kwargs): + if self.active: + raise AttributeError("not while active") + func(self, *args, **kwargs) + return nw + class IoMixin(object): EVENT_MASK = 0 - def __init__(self, loop, fd, events, ref=True, priority=None): + def __init__(self, loop, fd, events, ref=True, priority=None, _args=None): # XXX: Win32: Need to vfd_open the fd and free the old one? # XXX: Win32: Need a destructor to free the old fd? if fd < 0: raise ValueError('fd must be non-negative: %r' % fd) if events & ~self.EVENT_MASK: raise ValueError('illegal event mask: %r' % events) - super(IoMixin, self).__init__(loop, ref=ref, priority=priority, args=(fd, events)) + super(IoMixin, self).__init__(loop, ref=ref, priority=priority, + args=_args or (fd, events)) def start(self, callback, *args, **kwargs): args = args or _NOARGS diff --git a/src/gevent/core.py b/src/gevent/core.py index 5019974440180e552f9389470940ee3ef3c68f1f..07a0c8822007c82218541cc63a6fadc1a721b0f0 100644 --- a/src/gevent/core.py +++ b/src/gevent/core.py @@ -15,7 +15,12 @@ except ImportError: raise # CFFI/PyPy - from gevent.libev import corecffi as _core + lib = os.environ.get('GEVENT_CORE_CFFI_ONLY') + if lib == 'libuv': + from gevent.libuv import loop as _core + else: + from gevent.libev import corecffi as _core + copy_globals(_core, globals()) diff --git a/src/gevent/libuv/_corecffi_cdef.c b/src/gevent/libuv/_corecffi_cdef.c index 3d03d8741c1af98ed75cb8ddeafa7ae4bc0a58cf..5e9c28fe3176b49781c6a7b5a415186fb7872067 100644 --- a/src/gevent/libuv/_corecffi_cdef.c +++ b/src/gevent/libuv/_corecffi_cdef.c @@ -113,24 +113,24 @@ typedef struct uv_fs_poll_s uv_fs_poll_t; // callbacks with the same signature -typedef void (*uv_close_cb)(uv_handle_t *handle); -typedef void (*uv_idle_cb)(uv_idle_t *handle); -typedef void (*uv_timer_cb)(uv_timer_t *handle); -typedef void (*uv_check_cb)(uv_check_t* handle); -typedef void (*uv_async_cb)(uv_async_t* handle); -typedef void (*uv_prepare_cb)(uv_prepare_t *handle); +typedef void (*uv_close_cb)(void *handle); +typedef void (*uv_idle_cb)(void *handle); +typedef void (*uv_timer_cb)(void *handle); +typedef void (*uv_check_cb)(void* handle); +typedef void (*uv_async_cb)(void* handle); +typedef void (*uv_prepare_cb)(void*handle); // callbacks with distinct sigs -typedef void (*uv_walk_cb)(uv_handle_t *handle, void *arg); -typedef void (*uv_poll_cb)(uv_poll_t *handle, int status, int events); -typedef void (*uv_signal_cb)(uv_signal_t *handle, int signum); +typedef void (*uv_walk_cb)(void *handle, void *arg); +typedef void (*uv_poll_cb)(void *handle, int status, int events); +typedef void (*uv_signal_cb)(void *handle, int signum); // Callback passed to uv_fs_event_start() which will be called // repeatedly after the handle is started. If the handle was started // with a directory the filename parameter will be a relative path to // a file contained in the directory. The events parameter is an ORed // mask of uv_fs_event elements. -typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status); +typedef void (*uv_fs_event_cb)(void* handle, const char* filename, int events, int status); typedef struct { long tv_sec; @@ -288,10 +288,10 @@ static void (*gevent_noop)(void* handle); * watcher types has a 'void* data' that stores the CFFI handle to the Python watcher * object. */ -static void _gevent_generic_callback0(uv_handle_t* handle); // no extra args -static void _gevent_generic_callback1(uv_handle_t* handle, int arg); // one extra args. Everything will funnel through this -static void _gevent_poll_callback2(uv_handle_t* handle, int status, int events); -static void _gevent_fs_event_callback3(uv_handle_t* handle, const char* filename, int events, int status); +static void _gevent_generic_callback0(void* handle); // no extra args +static void _gevent_generic_callback1(void* handle, int arg); // one extra args. Everything will funnel through this +static void _gevent_poll_callback2(void* handle, int status, int events); +static void _gevent_fs_event_callback3(void* handle, const char* filename, int events, int status); typedef struct _gevent_fs_poll_s { uv_fs_poll_t handle; diff --git a/src/gevent/libuv/_corecffi_source.c b/src/gevent/libuv/_corecffi_source.c index 27214a6db207d6b10a38b2b99f0fc8aac7ccf95e..5228cfd936d7910c0461ae60080930450efe5268 100644 --- a/src/gevent/libuv/_corecffi_source.c +++ b/src/gevent/libuv/_corecffi_source.c @@ -8,8 +8,9 @@ static void _gevent_noop(void*handle) {} static void (*gevent_noop)(void* handle) = &_gevent_noop; -static void _gevent_generic_callback1(uv_handle_t* watcher, int arg) +static void _gevent_generic_callback1(void* vwatcher, int arg) { + uv_handle_t* watcher = (uv_handle_t*)vwatcher; void* handle = watcher->data; int cb_result = python_callback(handle, arg); switch(cb_result) { @@ -34,17 +35,17 @@ static void _gevent_generic_callback1(uv_handle_t* watcher, int arg) } -static void _gevent_generic_callback0(uv_handle_t* handle) +static void _gevent_generic_callback0(void* handle) { _gevent_generic_callback1(handle, 0); } -static void _gevent_poll_callback2(uv_handle_t* handle, int status, int events) +static void _gevent_poll_callback2(void* handle, int status, int events) { _gevent_generic_callback1(handle, status < 0 ? status : events); } -static void _gevent_fs_event_callback3(uv_handle_t* handle, const char* filename, int events, int status) +static void _gevent_fs_event_callback3(void* handle, const char* filename, int events, int status) { _gevent_generic_callback1(handle, status < 0 ? status : events); }