Windows: Use 32-bit distribution of python

This commit is contained in:
James Taylor
2018-09-14 19:32:27 -07:00
parent 6ca20ff701
commit 4212164e91
166 changed files with 175548 additions and 44620 deletions

View File

@@ -64,7 +64,8 @@ struct ev_loop {
// Watcher types
// base for all watchers
struct ev_watcher{
GEVENT_STRUCT_DONE _;
void* data;
GEVENT_STRUCT_DONE _;
};
struct ev_io {
@@ -137,6 +138,9 @@ unsigned int ev_embeddable_backends (void);
ev_tstamp ev_time (void);
void ev_set_syserr_cb(void *);
void ev_set_userdata(struct ev_loop*, void*);
void* ev_userdata(struct ev_loop*);
int ev_priority(void*);
void ev_set_priority(void*, int);
@@ -212,10 +216,19 @@ void (*gevent_noop)(struct ev_loop *_loop, struct ev_timer *w, int revents);
void ev_sleep (ev_tstamp delay); /* sleep for a while */
/* gevent callbacks */
static int (*python_callback)(void* handle, int revents);
static void (*python_handle_error)(void* handle, int revents);
static void (*python_stop)(void* handle);
/* These will be created as static functions at the end of the
* _source.c and must be declared there too.
*/
extern "Python" {
int python_callback(void* handle, int revents);
void python_handle_error(void* handle, int revents);
void python_stop(void* handle);
void python_check_callback(struct ev_loop*, void*, int);
void python_prepare_callback(struct ev_loop*, void*, int);
// libev specific
void _syserr_cb(char*);
}
/*
* We use a single C callback for every watcher type, which in turn calls the
* Python callbacks. The ev_watcher pointer type can be used for every watcher type
@@ -224,3 +237,7 @@ static void (*python_stop)(void* handle);
* object.
*/
static void _gevent_generic_callback(struct ev_loop* loop, struct ev_watcher* watcher, int revents);
static void gevent_zero_check(struct ev_check* handle);
static void gevent_zero_timer(struct ev_timer* handle);
static void gevent_zero_prepare(struct ev_prepare* handle);

View File

@@ -13,9 +13,10 @@ static void
_gevent_noop(struct ev_loop *_loop, struct ev_timer *w, int revents) { }
void (*gevent_noop)(struct ev_loop *, struct ev_timer *, int) = &_gevent_noop;
static int (*python_callback)(void* handle, int revents);
static void (*python_handle_error)(void* handle, int revents);
static void (*python_stop)(void* handle);
static int python_callback(void* handle, int revents);
static void python_handle_error(void* handle, int revents);
static void python_stop(void* handle);
static void _gevent_generic_callback(struct ev_loop* loop,
struct ev_watcher* watcher,
@@ -30,7 +31,7 @@ static void _gevent_generic_callback(struct ev_loop* loop,
// and allowing memory to be freed
python_handle_error(handle, revents);
break;
case 0:
case 1:
// Code to stop the event. Note that if python_callback
// has disposed of the last reference to the handle,
// `watcher` could now be invalid/disposed memory!
@@ -38,8 +39,31 @@ static void _gevent_generic_callback(struct ev_loop* loop,
python_stop(handle);
}
break;
default:
assert(cb_result == 1);
case 2:
// watcher is already stopped and dead, nothing to do.
break;
default:
fprintf(stderr,
"WARNING: gevent: Unexpected return value %d from Python callback "
"for watcher %p and handle %d\n",
cb_result,
watcher, handle);
// XXX: Possible leaking of resources here? Should we be
// closing the watcher?
}
}
static void gevent_zero_timer(struct ev_timer* handle)
{
memset(handle, 0, sizeof(struct ev_timer));
}
static void gevent_zero_check(struct ev_check* handle)
{
memset(handle, 0, sizeof(struct ev_check));
}
static void gevent_zero_prepare(struct ev_prepare* handle)
{
memset(handle, 0, sizeof(struct ev_prepare));
}

View File

@@ -1,42 +1,29 @@
/* Copyright (c) 2011-2012 Denis Bilenko. See LICENSE for details. */
#include <stddef.h>
#include "Python.h"
#include "ev.h"
#include "corecext.h"
#include "callbacks.h"
#ifdef Py_PYTHON_H
/* the name changes depending on our file layout and --module-name option */
#define _GEVENTLOOP struct __pyx_vtabstruct_6gevent_5libev_8corecext_loop
#if PY_MAJOR_VERSION >= 3
#define PyInt_FromLong PyLong_FromLong
#endif
static void gevent_handle_error(struct PyGeventLoopObject* loop, PyObject* context) {
PyThreadState *tstate;
PyObject *type, *value, *traceback, *result;
tstate = PyThreadState_GET();
type = tstate->curexc_type;
if (!type)
return;
value = tstate->curexc_value;
traceback = tstate->curexc_traceback;
if (!value) value = Py_None;
if (!traceback) traceback = Py_None;
Py_INCREF(type);
Py_INCREF(value);
Py_INCREF(traceback);
PyErr_Clear();
result = ((_GEVENTLOOP *)loop->__pyx_vtab)->handle_error(loop, context, type, value, traceback, 0);
if (result) {
Py_DECREF(result);
}
else {
PyErr_Print();
PyErr_Clear();
}
Py_DECREF(type);
Py_DECREF(value);
Py_DECREF(traceback);
}
#ifndef CYTHON_INLINE
#if defined(__clang__)
#define CYTHON_INLINE __inline__ __attribute__ ((__unused__))
#elif defined(__GNUC__)
#define CYTHON_INLINE __inline__
#elif defined(_MSC_VER)
#define CYTHON_INLINE __inline
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define CYTHON_INLINE inline
#else
#define CYTHON_INLINE
#endif
#endif
static CYTHON_INLINE void gevent_check_signals(struct PyGeventLoopObject* loop) {
@@ -69,7 +56,7 @@ static void gevent_stop(PyObject* watcher, struct PyGeventLoopObject* loop) {
error = 1;
method = PyObject_GetAttrString(watcher, "stop");
if (method) {
result = PyObject_Call(method, __pyx_empty_tuple, NULL);
result = PyObject_Call(method, _empty_tuple, NULL);
if (result) {
Py_DECREF(result);
error = 0;
@@ -94,7 +81,7 @@ static void gevent_callback(struct PyGeventLoopObject* loop, PyObject* callback,
Py_INCREF(watcher);
gevent_check_signals(loop);
if (args == Py_None) {
args = __pyx_empty_tuple;
args = _empty_tuple;
}
length = PyTuple_Size(args);
if (length < 0) {
@@ -143,7 +130,7 @@ end:
}
static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb) {
void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb) {
/* no need for GIL here because it is only called from run_callbacks which already has GIL */
PyObject *result, *callback, *args;
if (!loop || !cb)
@@ -179,11 +166,16 @@ static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallback
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
#define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \
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); \
void gevent_callback_##WATCHER_LC(struct ev_loop *_loop, void *c_watcher, int revents) { \
struct PyGeventWatcherObject* watcher = (struct PyGeventWatcherObject*)GET_OBJECT(PyGevent##WATCHER_TYPE##Object, c_watcher, _watcher); \
gevent_callback(watcher->loop, watcher->_callback, watcher->args, (PyObject*)watcher, c_watcher, revents); \
}
@@ -191,7 +183,7 @@ static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallback
DEFINE_CALLBACKS
static void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int revents) {
void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int revents) {
struct PyGeventLoopObject* loop;
PyObject *result;
GIL_DECLARE;
@@ -199,7 +191,7 @@ static void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int reven
loop = GET_OBJECT(PyGeventLoopObject, watcher, _prepare);
Py_INCREF(loop);
gevent_check_signals(loop);
result = ((_GEVENTLOOP *)loop->__pyx_vtab)->_run_callbacks(loop);
result = gevent_loop_run_callbacks(loop);
if (result) {
Py_DECREF(result);
}
@@ -211,15 +203,14 @@ static void gevent_run_callbacks(struct ev_loop *_loop, void *watcher, int reven
GIL_RELEASE;
}
#if defined(_WIN32)
/* This is only used on Win32 */
static void gevent_periodic_signal_check(struct ev_loop *_loop, void *watcher, int revents) {
void gevent_periodic_signal_check(struct ev_loop *_loop, void *watcher, int revents) {
GIL_DECLARE;
GIL_ENSURE;
gevent_check_signals(GET_OBJECT(PyGeventLoopObject, watcher, _periodic_signal_checker));
GIL_RELEASE;
}
#endif /* _WIN32 */
#endif /* Py_PYTHON_H */

View File

@@ -1,5 +1,9 @@
struct ev_loop;
struct PyGeventLoopObject;
struct PyGeventCallbackObject;
#define DEFINE_CALLBACK(WATCHER_LC, WATCHER_TYPE) \
static void gevent_callback_##WATCHER_LC(struct ev_loop *, void *, int);
void gevent_callback_##WATCHER_LC(struct ev_loop *, void *, int);
#define DEFINE_CALLBACKS0 \
@@ -11,33 +15,24 @@
DEFINE_CALLBACK(check, Check); \
DEFINE_CALLBACK(fork, Fork); \
DEFINE_CALLBACK(async, Async); \
DEFINE_CALLBACK(stat, Stat);
DEFINE_CALLBACK(stat, Stat); \
DEFINE_CALLBACK(child, Child);
#ifndef _WIN32
#define DEFINE_CALLBACKS \
DEFINE_CALLBACKS0 \
DEFINE_CALLBACK(child, Child)
#else
#define DEFINE_CALLBACKS DEFINE_CALLBACKS0
#endif
DEFINE_CALLBACKS
static void gevent_run_callbacks(struct ev_loop *, void *, int);
struct PyGeventLoopObject;
static void gevent_handle_error(struct PyGeventLoopObject* loop, PyObject* context);
struct PyGeventCallbackObject;
static void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb);
void gevent_run_callbacks(struct ev_loop *, void *, int);
#if defined(_WIN32)
static void gevent_periodic_signal_check(struct ev_loop *, void *, int);
#endif
static void gevent_noop(struct ev_loop *_loop, void *watcher, int revents) { }
void gevent_call(struct PyGeventLoopObject* loop, struct PyGeventCallbackObject* cb);
static void gevent_noop(struct ev_loop *_loop, void *watcher, int revents) {
}
/* Only used on Win32 */
void gevent_periodic_signal_check(struct ev_loop *, void *, int);

22963
python/gevent/libev/corecext.c Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,147 @@
/* Generated by Cython 0.28.5 */
#ifndef __PYX_HAVE__gevent__libev__corecext
#define __PYX_HAVE__gevent__libev__corecext
struct PyGeventCallbackObject;
struct PyGeventLoopObject;
struct PyGeventWatcherObject;
struct PyGeventIOObject;
struct PyGeventTimerObject;
struct PyGeventSignalObject;
struct PyGeventIdleObject;
struct PyGeventPrepareObject;
struct PyGeventCheckObject;
struct PyGeventForkObject;
struct PyGeventAsyncObject;
struct PyGeventChildObject;
struct PyGeventStatObject;
struct PyGeventCallbackObject {
PyObject_HEAD
PyObject *callback;
PyObject *args;
struct PyGeventCallbackObject *next;
};
struct PyGeventLoopObject {
PyObject_HEAD
struct __pyx_vtabstruct_6gevent_5libev_8corecext_loop *__pyx_vtab;
struct ev_prepare _prepare;
struct ev_timer _timer0;
struct ev_timer _periodic_signal_checker;
PyObject *error_handler;
struct ev_loop *_ptr;
struct __pyx_obj_6gevent_5libev_8corecext_CallbackFIFO *_callbacks;
int starting_timer_may_update_loop_time;
int _default;
};
struct PyGeventWatcherObject {
PyObject_HEAD
struct PyGeventLoopObject *loop;
PyObject *_callback;
PyObject *args;
struct ev_watcher *__pyx___watcher;
struct __pyx_t_6gevent_5libev_8corecext_start_and_stop *__pyx___ss;
unsigned int _flags;
};
struct PyGeventIOObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_io _watcher;
};
struct PyGeventTimerObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_timer _watcher;
};
struct PyGeventSignalObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_signal _watcher;
};
struct PyGeventIdleObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_idle _watcher;
};
struct PyGeventPrepareObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_prepare _watcher;
};
struct PyGeventCheckObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_check _watcher;
};
struct PyGeventForkObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_fork _watcher;
};
struct PyGeventAsyncObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_async _watcher;
};
struct PyGeventChildObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_child _watcher;
};
struct PyGeventStatObject {
struct PyGeventWatcherObject __pyx_base;
struct ev_stat _watcher;
PyObject *path;
PyObject *_paths;
};
#ifndef __PYX_HAVE_API__gevent__libev__corecext
#ifndef __PYX_EXTERN_C
#ifdef __cplusplus
#define __PYX_EXTERN_C extern "C"
#else
#define __PYX_EXTERN_C extern
#endif
#endif
#ifndef DL_IMPORT
#define DL_IMPORT(_T) _T
#endif
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventCallback_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventLoop_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventWatcher_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventIO_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventTimer_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventSignal_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventIdle_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventPrepare_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventCheck_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventFork_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventAsync_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventChild_Type;
__PYX_EXTERN_C DL_IMPORT(PyTypeObject) PyGeventStat_Type;
__PYX_EXTERN_C void gevent_handle_error(struct PyGeventLoopObject *, PyObject *);
__PYX_EXTERN_C PyObject *gevent_loop_run_callbacks(struct PyGeventLoopObject *);
__PYX_EXTERN_C PyObject *GEVENT_CORE_EVENTS;
__PYX_EXTERN_C PyObject *_empty_tuple;
#endif /* !__PYX_HAVE_API__gevent__libev__corecext */
/* WARNING: the interface of the module init function changed in CPython 3.5. */
/* It now returns a PyModuleDef instance instead of a PyModule instance. */
#if PY_MAJOR_VERSION < 3
PyMODINIT_FUNC initcorecext(void);
#else
PyMODINIT_FUNC PyInit_corecext(void);
#endif
#endif /* !__PYX_HAVE__gevent__libev__corecext */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,42 @@
#if defined(LIBEV_EMBED)
#include "ev.c"
#undef LIBEV_EMBED
#define LIBEV_EMBED 1
#define gevent_ev_loop_origflags(loop) ((loop)->origflags)
#define gevent_ev_loop_sig_pending(loop) ((loop))->sig_pending
#define gevent_ev_loop_backend_fd(loop) ((loop))->backend_fd
#define gevent_ev_loop_activecnt(loop) ((loop))->activecnt
#if EV_USE_SIGNALFD
#define gevent_ev_loop_sigfd(loop) ((loop))->sigfd
#else
#define gevent_ev_loop_sigfd(loop) -1
#endif /* !EV_USE_SIGNALFD */
#else /* !LIBEV_EMBED */
#include "ev.h"
#define gevent_ev_loop_origflags(loop) -1
#define gevent_ev_loop_sig_pending(loop) -1
#define gevent_ev_loop_backend_fd(loop) -1
#define gevent_ev_loop_activecnt(loop) -1
#define gevent_ev_loop_sigfd(loop) -1
#define LIBEV_EMBED 0
#define EV_USE_FLOOR -1
#define EV_USE_CLOCK_SYSCALL -1
#define EV_USE_REALTIME -1
#define EV_USE_MONOTONIC -1
#define EV_USE_NANOSLEEP -1
#define EV_USE_INOTIFY -1
#define EV_USE_SIGNALFD -1
#define EV_USE_EVENTFD -1
#define EV_USE_4HEAP -1
#ifndef _WIN32
#include <signal.h>
#endif
#endif /* !_WIN32 */
#endif
#endif /* LIBEV_EMBED */
#ifndef _WIN32
@@ -58,9 +87,14 @@ static void gevent_reset_sigchld_handler(void) {
}
}
#else
#else /* !_WIN32 */
#define gevent_ev_default_loop ev_default_loop
static void gevent_install_sigchld_handler(void) { }
static void gevent_reset_sigchld_handler(void) { }
#endif
// Fake child functions that we can link to.
static void ev_child_start(struct ev_loop* loop, ev_child* w) {};
static void ev_child_stop(struct ev_loop* loop, ev_child* w) {};
#endif /* _WIN32 */

View File

@@ -1,18 +1,22 @@
# From cython/includes/libc/stdint.pxd
# Longness only used for type promotion.
# Actual compile time size used for conversions.
# We don't have stdint.h on visual studio 9.0 (2008) on windows, sigh,
# so go with Py_ssize_t
# ssize_t -> intptr_t
cdef extern from "libev_vfd.h":
#ifdef _WIN32
#ifdef _WIN64
ctypedef long long vfd_socket_t
#else
ctypedef long vfd_socket_t
#endif
#else
ctypedef int vfd_socket_t
#endif
long vfd_get(int)
# cython doesn't process pre-processor directives, so they
# don't matter in this file. It just takes the last definition it sees.
ctypedef Py_ssize_t intptr_t
ctypedef intptr_t vfd_socket_t
vfd_socket_t vfd_get(int)
int vfd_open(long) except -1
void vfd_free(int)
cdef extern from "libev.h":
cdef extern from "libev.h" nogil:
int LIBEV_EMBED
int EV_MINPRI
int EV_MAXPRI
@@ -87,6 +91,9 @@ cdef extern from "libev.h":
int sigfd
unsigned int origflags
struct ev_watcher:
void* data;
struct ev_io:
int fd
int events
@@ -125,6 +132,13 @@ cdef extern from "libev.h":
stat prev
double interval
union ev_any_watcher:
ev_watcher w
ev_io io
ev_timer timer
ev_signal signal
ev_idle idle
int ev_version_major()
int ev_version_minor()
@@ -132,7 +146,9 @@ cdef extern from "libev.h":
unsigned int ev_recommended_backends()
unsigned int ev_embeddable_backends()
double ev_time()
ctypedef double ev_tstamp
ev_tstamp ev_time()
void ev_set_syserr_cb(void *)
int ev_priority(void*)
@@ -186,6 +202,8 @@ cdef extern from "libev.h":
ev_loop* ev_default_loop(unsigned int flags)
ev_loop* ev_loop_new(unsigned int flags)
void* ev_userdata(ev_loop*)
void ev_set_userdata(ev_loop*, void*)
void ev_loop_destroy(ev_loop*)
void ev_loop_fork(ev_loop*)
int ev_is_default_loop(ev_loop*)
@@ -195,7 +213,7 @@ cdef extern from "libev.h":
void ev_verify(ev_loop*)
void ev_run(ev_loop*, int flags) nogil
double ev_now(ev_loop*)
ev_tstamp ev_now(ev_loop*)
void ev_now_update(ev_loop*)
void ev_ref(ev_loop*)
@@ -203,6 +221,15 @@ cdef extern from "libev.h":
void ev_break(ev_loop*, int)
unsigned int ev_pending_count(ev_loop*)
# gevent extra functions. These are defined in libev.h.
ev_loop* gevent_ev_default_loop(unsigned int flags)
void gevent_install_sigchld_handler()
void gevent_reset_sigchld_handler()
# These compensate for lack of access to ev_loop struct definition
# when LIBEV_EMBED is false.
unsigned int gevent_ev_loop_origflags(ev_loop*);
int gevent_ev_loop_sig_pending(ev_loop*);
int gevent_ev_loop_backend_fd(ev_loop*);
int gevent_ev_loop_activecnt(ev_loop*);
int gevent_ev_loop_sigfd(ev_loop*);

View File

@@ -1,11 +1,12 @@
#ifdef _WIN32
#ifdef _WIN64
typedef PY_LONG_LONG vfd_socket_t;
/* see discussion in the libuv directory: this is a SOCKET which is a
HANDLE which is a PVOID (even though they're really small ints),
and CPython and PyPy return that SOCKET cast to an int from
fileno()
*/
typedef intptr_t vfd_socket_t;
#define vfd_socket_object PyLong_FromLongLong
#else
typedef long vfd_socket_t;
#define vfd_socket_object PyInt_FromLong
#endif
#ifdef LIBEV_EMBED
/*
* If libev on win32 is embedded, then we can use an
@@ -53,13 +54,13 @@ static CRITICAL_SECTION* vfd_make_lock()
#define VFD_GIL_DECLARE PyGILState_STATE ___save
#define VFD_GIL_ENSURE ___save = PyGILState_Ensure()
#define VFD_GIL_RELEASE PyGILState_Release(___save)
#else
#else /* ! WITH_THREAD */
#define VFD_LOCK_ENTER
#define VFD_LOCK_LEAVE
#define VFD_GIL_DECLARE
#define VFD_GIL_ENSURE
#define VFD_GIL_RELEASE
#endif
#endif /*_WITH_THREAD */
/*
* Given a virtual fd returns an OS handle or -1
@@ -67,7 +68,7 @@ static CRITICAL_SECTION* vfd_make_lock()
*/
static vfd_socket_t vfd_get(int fd)
{
int handle = -1;
vfd_socket_t handle = -1;
VFD_LOCK_ENTER;
if (vfd_entries != NULL && fd >= 0 && fd < vfd_num)
handle = vfd_entries[fd].handle;
@@ -201,7 +202,7 @@ done:
#define vfd_free(fd) vfd_free_((fd), 0)
#define EV_WIN32_CLOSE_FD(fd) vfd_free_((fd), 1)
#else
#else /* !LIBEV_EMBED */
/*
* If libev on win32 is not embedded in gevent, then
* the only way to map vfds is to use the default of
@@ -211,13 +212,14 @@ done:
#define vfd_get(fd) _get_osfhandle((fd))
#define vfd_open(fd) _open_osfhandle((fd), 0)
#define vfd_free(fd)
#endif
#else
#endif /* LIBEV_EMBED */
#else /* !_WIN32 */
/*
* On non-win32 platforms vfd_* are noop macros
*/
typedef int vfd_socket_t;
#define vfd_get(fd) (fd)
#define vfd_open(fd) ((int)(fd))
#define vfd_open(fd) (fd)
#define vfd_free(fd)
#endif
#endif /* _WIN32 */

View File

@@ -0,0 +1,282 @@
# pylint: disable=too-many-lines, protected-access, redefined-outer-name, not-callable
# pylint: disable=no-member
from __future__ import absolute_import, print_function
import sys
from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error
ffi = _corecffi.ffi # pylint:disable=no-member
libev = _corecffi.lib # pylint:disable=no-member
if hasattr(libev, 'vfd_open'):
# Must be on windows
assert sys.platform.startswith("win"), "vfd functions only needed on windows"
vfd_open = libev.vfd_open
vfd_free = libev.vfd_free
vfd_get = libev.vfd_get
else:
vfd_open = vfd_free = vfd_get = lambda fd: fd
#####
## NOTE on Windows:
# The C implementation does several things specially for Windows;
# a possibly incomplete list is:
#
# - the loop runs a periodic signal checker;
# - the io watcher constructor is different and it has a destructor;
# - the child watcher is not defined
#
# The CFFI implementation does none of these things, and so
# is possibly NOT FUNCTIONALLY CORRECT on Win32
#####
_NOARGS = ()
_events = [(libev.EV_READ, 'READ'),
(libev.EV_WRITE, 'WRITE'),
(libev.EV__IOFDSET, '_IOFDSET'),
(libev.EV_PERIODIC, 'PERIODIC'),
(libev.EV_SIGNAL, 'SIGNAL'),
(libev.EV_CHILD, 'CHILD'),
(libev.EV_STAT, 'STAT'),
(libev.EV_IDLE, 'IDLE'),
(libev.EV_PREPARE, 'PREPARE'),
(libev.EV_CHECK, 'CHECK'),
(libev.EV_EMBED, 'EMBED'),
(libev.EV_FORK, 'FORK'),
(libev.EV_CLEANUP, 'CLEANUP'),
(libev.EV_ASYNC, 'ASYNC'),
(libev.EV_CUSTOM, 'CUSTOM'),
(libev.EV_ERROR, 'ERROR')]
from gevent._ffi import watcher as _base
def _events_to_str(events):
return _base.events_to_str(events, _events)
class watcher(_base.watcher):
_FFI = ffi
_LIB = libev
_watcher_prefix = 'ev'
# Flags is a bitfield with the following meaning:
# 0000 -> default, referenced (when active)
# 0010 -> ev_unref has been called
# 0100 -> not referenced; independent of 0010
_flags = 0
def __init__(self, _loop, ref=True, priority=None, args=_base._NOARGS):
if ref:
self._flags = 0
else:
self._flags = 4
super(watcher, self).__init__(_loop, ref=ref, priority=priority, args=args)
def _watcher_ffi_set_priority(self, priority):
libev.ev_set_priority(self._watcher, priority)
def _watcher_ffi_init(self, args):
self._watcher_init(self._watcher,
self._watcher_callback,
*args)
def _watcher_ffi_start(self):
self._watcher_start(self.loop._ptr, self._watcher)
def _watcher_ffi_ref(self):
if self._flags & 2: # we've told libev we're not referenced
self.loop.ref()
self._flags &= ~2
def _watcher_ffi_unref(self):
if self._flags & 6 == 4:
# We're not referenced, but we haven't told libev that
self.loop.unref()
self._flags |= 2 # now we've told libev
def _get_ref(self):
return False if self._flags & 4 else True
def _set_ref(self, value):
if value:
if not self._flags & 4:
return # ref is already True
if self._flags & 2: # ev_unref was called, undo
self.loop.ref()
self._flags &= ~6 # do not want unref, no outstanding unref
else:
if self._flags & 4:
return # ref is already False
self._flags |= 4 # we're not referenced
if not self._flags & 2 and libev.ev_is_active(self._watcher):
# we haven't told libev we're not referenced, but it thinks we're
# active so we need to undo that
self.loop.unref()
self._flags |= 2 # libev knows we're not referenced
ref = property(_get_ref, _set_ref)
def _get_priority(self):
return libev.ev_priority(self._watcher)
@_base.not_while_active
def _set_priority(self, priority):
libev.ev_set_priority(self._watcher, priority)
priority = property(_get_priority, _set_priority)
def feed(self, revents, callback, *args):
self.callback = callback
self.args = args or _NOARGS
if self._flags & 6 == 4:
self.loop.unref()
self._flags |= 2
libev.ev_feed_event(self.loop._ptr, self._watcher, revents)
if not self._flags & 1:
# Py_INCREF(<PyObjectPtr>self)
self._flags |= 1
@property
def pending(self):
return True if self._watcher and libev.ev_is_pending(self._watcher) else False
class io(_base.IoMixin, watcher):
EVENT_MASK = libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE
def _get_fd(self):
return vfd_get(self._watcher.fd)
@_base.not_while_active
def _set_fd(self, fd):
vfd = vfd_open(fd)
vfd_free(self._watcher.fd)
self._watcher_init(self._watcher, self._watcher_callback, vfd, self._watcher.events)
fd = property(_get_fd, _set_fd)
def _get_events(self):
return self._watcher.events
@_base.not_while_active
def _set_events(self, events):
self._watcher_init(self._watcher, self._watcher_callback, self._watcher.fd, events)
events = property(_get_events, _set_events)
@property
def events_str(self):
return _events_to_str(self._watcher.events)
def _format(self):
return ' fd=%s events=%s' % (self.fd, self.events_str)
class timer(_base.TimerMixin, watcher):
@property
def at(self):
return self._watcher.at
def again(self, callback, *args, **kw):
# Exactly the same as start(), just with a different initializer
# function
self._watcher_start = libev.ev_timer_again
try:
self.start(callback, *args, **kw)
finally:
del self._watcher_start
class signal(_base.SignalMixin, watcher):
pass
class idle(_base.IdleMixin, watcher):
pass
class prepare(_base.PrepareMixin, watcher):
pass
class check(_base.CheckMixin, watcher):
pass
class fork(_base.ForkMixin, watcher):
pass
class async_(_base.AsyncMixin, watcher):
def send(self):
libev.ev_async_send(self.loop._ptr, self._watcher)
@property
def pending(self):
return True if libev.ev_async_pending(self._watcher) else False
# Provide BWC for those that have async
locals()['async'] = async_
class _ClosedWatcher(object):
__slots__ = ('pid', 'rpid', 'rstatus')
def __init__(self, other):
self.pid = other.pid
self.rpid = other.rpid
self.rstatus = other.rstatus
def __bool__(self):
return False
__nonzero__ = __bool__
class child(_base.ChildMixin, watcher):
_watcher_type = 'child'
def close(self):
# Capture the properties we defer to our _watcher, because
# we're about to discard it.
closed_watcher = _ClosedWatcher(self._watcher)
super(child, self).close()
self._watcher = closed_watcher
@property
def pid(self):
return self._watcher.pid
@property
def rpid(self):
return self._watcher.rpid
@rpid.setter
def rpid(self, value):
self._watcher.rpid = value
@property
def rstatus(self):
return self._watcher.rstatus
@rstatus.setter
def rstatus(self, value):
self._watcher.rstatus = value
class stat(_base.StatMixin, watcher):
_watcher_type = 'stat'
@property
def attr(self):
if not self._watcher.attr.st_nlink:
return
return self._watcher.attr
@property
def prev(self):
if not self._watcher.prev.st_nlink:
return
return self._watcher.prev
@property
def interval(self):
return self._watcher.interval