Christian Heimes added the comment:
Added license header to test_epoll.
Some C code cleanups
Added file: http://bugs.python.org/file8999/trunk_select_epoll3.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1657>
__________________________________
Index: configure
===================================================================
--- configure (Revision 59566)
+++ configure (Arbeitskopie)
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 59533 .
+# From configure.in Revision: 59558 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for python 2.6.
#
@@ -5416,13 +5416,14 @@
+
for ac_header in asm/types.h conio.h curses.h direct.h dlfcn.h errno.h \
fcntl.h grp.h \
io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \
shadow.h signal.h stdint.h stropts.h termios.h thread.h \
unistd.h utime.h \
-sys/audioio.h sys/bsdtty.h sys/file.h sys/loadavg.h sys/lock.h sys/mkdev.h \
-sys/modem.h \
+sys/audioio.h sys/bsdtty.h sys/epoll.h sys/file.h sys/loadavg.h sys/lock.h \
+sys/mkdev.h sys/modem.h \
sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \
sys/time.h \
sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \
@@ -15644,7 +15645,57 @@
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: checking for epoll" >&5
+echo $ECHO_N "checking for epoll... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/epoll.h>
+int
+main ()
+{
+void *x=epoll_create
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EPOLL 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# On some systems (eg. FreeBSD 5), we would find a definition of the
# functions ctermid_r, setgroups in the library, but no prototype
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
Index: configure.in
===================================================================
--- configure.in (Revision 59566)
+++ configure.in (Arbeitskopie)
@@ -1100,8 +1100,8 @@
io.h langinfo.h libintl.h ncurses.h poll.h process.h pthread.h \
shadow.h signal.h stdint.h stropts.h termios.h thread.h \
unistd.h utime.h \
-sys/audioio.h sys/bsdtty.h sys/file.h sys/loadavg.h sys/lock.h sys/mkdev.h \
-sys/modem.h \
+sys/audioio.h sys/bsdtty.h sys/epoll.h sys/file.h sys/loadavg.h sys/lock.h \
+sys/mkdev.h sys/modem.h \
sys/param.h sys/poll.h sys/select.h sys/socket.h sys/statvfs.h sys/stat.h \
sys/time.h \
sys/times.h sys/types.h sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h \
@@ -2358,7 +2358,12 @@
AC_MSG_RESULT(yes),
AC_MSG_RESULT(no)
)
-
+AC_MSG_CHECKING(for epoll)
+AC_TRY_COMPILE([#include <sys/epoll.h>], void *x=epoll_create,
+ AC_DEFINE(HAVE_EPOLL, 1, Define if you have the 'epoll' functions.)
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no)
+)
# On some systems (eg. FreeBSD 5), we would find a definition of the
# functions ctermid_r, setgroups in the library, but no prototype
# (e.g. because we use _XOPEN_SOURCE). See whether we can take their
Index: Doc/library/select.rst
===================================================================
--- Doc/library/select.rst (Revision 59566)
+++ Doc/library/select.rst (Arbeitskopie)
@@ -7,10 +7,11 @@
This module provides access to the :cfunc:`select` and :cfunc:`poll` functions
-available in most operating systems. Note that on Windows, it only works for
-sockets; on other operating systems, it also works for other file types (in
-particular, on Unix, it works on pipes). It cannot be used on regular files to
-determine whether a file has grown since it was last read.
+available in most operating systems and :cfunc:`epoll` available on Linux 2.5+.
+Note that on Windows, it only works for sockets; on other operating systems,
+it also works for other file types (in particular, on Unix, it works on pipes).
+It cannot be used on regular files to determine whether a file has grown since
+it was last read.
The module defines the following:
@@ -22,6 +23,16 @@
string, as would be printed by the C function :cfunc:`perror`.
+.. function:: epoll(sizehint)
+
+ (Only supported on Linux 2.5.44 and newer.) Returns an edge polling
+ object, which can be used as Edge or Level Triggered interface for I/O
+ events; see section :ref:`epoll-objects` below for the methods supported
+ by epolling objects.
+
+ .. versionadded:: 2.6
+
+
.. function:: poll()
(Not supported by all operating systems.) Returns a polling object, which
@@ -69,6 +80,74 @@
not handle file descriptors that don't originate from WinSock.
+.. _epoll-objects:
+
+Edge and Level Trigger Polling (epoll) Objects
+----------------------------------------------
+
+ *eventmask*
+
+ +------------------------+-----------------------------------------------+
+ | Constant | Meaning |
+ +========================+===============================================+
+ | :const:`EPOLL_IN` | Available for read |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_OUT` | Available for write |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_PRI` | Urgent data for read |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_ERR` | Error condition happend on the assoc. fd |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_HUP` | Hang up happend on the assoc. fd |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_ET` | Set Edge Trigger behavior, the default is |
+ | | Level Trigger behavior
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_ONESHOT` | Set one-shot behavior. After one event is |
+ | | pulled out, the fd is internally disabled |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_RDNORM` | ??? |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_RDBAND` | ??? |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_WRNORM` | ??? |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_WRBAND` | ??? |
+ +------------------------+-----------------------------------------------+
+ | :const:`EPOLL_MSG` | ??? |
+ +------------------------+-----------------------------------------------+
+
+
+.. method:: epoll.close()
+
+ Close the control file descriptor of the epoll object.
+
+
+.. method:: epoll.fileno()
+
+ Return the file descriptor number of the control fd.
+
+
+.. method:: epoll.register(fd[, eventmask])
+
+ Register a fd descriptor with the epoll object.
+
+
+.. method:: epoll.modify(fd, eventmask)
+
+ Modify a register file descriptor.
+
+
+.. method:: epoll.unregister(fd)
+
+ Remove a registered file descriptor from the epoll object.
+
+
+.. method:: epoll.wait(maxevents, timeout)
+
+ Wait for events.
+
+
.. _poll-objects:
Polling Objects
Index: Lib/test/test_epoll.py
===================================================================
--- Lib/test/test_epoll.py (Revision 0)
+++ Lib/test/test_epoll.py (Revision 0)
@@ -0,0 +1,191 @@
+# Copyright (c) 2001-2006 Twisted Matrix Laboratories.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""
+Tests for epoll wrapper.
+"""
+import socket, errno, time, select
+import unittest
+
+class EPoll(unittest.TestCase):
+ """
+ Tests for the low-level epoll bindings.
+ """
+ def setUp(self):
+ """
+ Create a listening server port and a list with which to keep track
+ of created sockets.
+ """
+ self.serverSocket = socket.socket()
+ self.serverSocket.bind(('127.0.0.1', 0))
+ self.serverSocket.listen(1)
+ self.connections = [self.serverSocket]
+
+
+ def tearDown(self):
+ """
+ Close any sockets which were opened by the test.
+ """
+ for skt in self.connections:
+ skt.close()
+
+
+ def _connected_pair(self):
+ """
+ Return the two sockets which make up a new TCP connection.
+ """
+ client = socket.socket()
+ client.setblocking(False)
+ try:
+ client.connect(('127.0.0.1', self.serverSocket.getsockname()[1]))
+ except socket.error, e:
+ self.assertEquals(e.args[0], errno.EINPROGRESS)
+ else:
+ raise AssertionError("Connect should have raised EINPROGRESS")
+ server, addr = self.serverSocket.accept()
+
+ self.connections.extend((client, server))
+ return client, server
+
+
+ def test_create(self):
+ """
+ Test the creation of an epoll object.
+ """
+ try:
+ ep = select.epoll(16)
+ except OSError, e:
+ raise AssertionError(str(e))
+ self.assert_(ep.fileno() > 0, ep.fileno())
+ self.assert_(not ep.closed)
+ ep.close()
+ self.assert_(ep.closed)
+ self.assertRaises(ValueError, ep.fileno)
+
+ def test_badcreate(self):
+ """
+ Test that attempting to create an epoll object with some random
+ objects raises a TypeError.
+ """
+ self.assertRaises(TypeError, select.epoll, 1, 2, 3)
+ self.assertRaises(TypeError, select.epoll, 'foo')
+ self.assertRaises(TypeError, select.epoll, None)
+ self.assertRaises(TypeError, select.epoll, ())
+ self.assertRaises(TypeError, select.epoll, ['foo'])
+ self.assertRaises(TypeError, select.epoll, {})
+ self.assertRaises(TypeError, select.epoll)
+
+
+ def test_add(self):
+ """
+ Test adding a socket to an epoll object.
+ """
+ server, client = self._connected_pair()
+
+ ep = select.epoll(2)
+ try:
+ ep.register(server.fileno(), select.EPOLL_IN | select.EPOLL_OUT)
+ ep.register(client.fileno(), select.EPOLL_IN | select.EPOLL_OUT)
+ finally:
+ ep.close()
+
+
+ def test_control_and_wait(self):
+ """
+ Test waiting on an epoll object which has had some sockets added to
+ it.
+ """
+ client, server = self._connected_pair()
+
+ ep = select.epoll(16)
+ ep.register(server.fileno(),
+ select.EPOLL_IN | select.EPOLL_OUT | select.EPOLL_ET)
+ ep.register(client.fileno(),
+ select.EPOLL_IN | select.EPOLL_OUT | select.EPOLL_ET)
+
+ now = time.time()
+ events = ep.wait(4, 1000)
+ then = time.time()
+ self.failIf(then - now > 0.1, then - now)
+
+ events.sort()
+ expected = [(client.fileno(), select.EPOLL_OUT),
+ (server.fileno(), select.EPOLL_OUT)]
+ expected.sort()
+
+ self.assertEquals(events, expected)
+ self.failIf(then - now > 0.01, then - now)
+
+ now = time.time()
+ events = ep.wait(4, 200)
+ then = time.time()
+ self.failIf(events)
+
+ client.send("Hello!")
+ server.send("world!!!")
+
+ now = time.time()
+ events = ep.wait(4, 1000)
+ then = time.time()
+ self.failIf(then - now > 0.01)
+
+ events.sort()
+ expected = [(client.fileno(), select.EPOLL_IN | select.EPOLL_OUT),
+ (server.fileno(), select.EPOLL_IN | select.EPOLL_OUT)]
+ expected.sort()
+
+ self.assertEquals(events, expected)
+
+ ep.unregister(client.fileno())
+ ep.modify(server.fileno(), select.EPOLL_OUT)
+ now = time.time()
+ events = ep.wait(4, 1000)
+ then = time.time()
+ self.failIf(then - now > 0.01)
+
+ expected = [(server.fileno(), select.EPOLL_OUT)]
+ self.assertEquals(events, expected)
+
+
+ def test_errors(self):
+ """
+ Test some error conditions of epoll methods.
+ """
+ self.assertRaises(IOError, select.epoll, -1)
+ self.assertRaises(IOError, select.epoll(1).register, -1,
+ select.EPOLL_IN)
+
+if not hasattr(select, "epoll") is None:
+ EPoll.skip = "select.epoll unavailable"
+else:
+ try:
+ e = select.epoll(16)
+ except IOError, exc:
+ if exc.errno == errno.ENOSYS:
+ del exc
+ EPoll.skip = "epoll support missing from platform"
+ else:
+ raise
+ else:
+ e.close()
+ del e
+
+if __name__ == '__main__':
+ unittest.main()
Eigenschaftsänderungen: Lib/test/test_epoll.py
___________________________________________________________________
Name: svn:keywords
+ 'Id Revision'
Name: svn:eol-style
+ native
Index: Modules/selectmodule.c
===================================================================
--- Modules/selectmodule.c (Revision 59566)
+++ Modules/selectmodule.c (Arbeitskopie)
@@ -31,6 +31,10 @@
#include <sys/poll.h>
#endif
+#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL)
+#include <sys/epoll.h>
+#endif
+
#ifdef __sgi
/* This is missing from unistd.h */
extern void bzero(void *, int);
@@ -483,9 +487,9 @@
return NULL;
/* call poll() */
- Py_BEGIN_ALLOW_THREADS;
+ Py_BEGIN_ALLOW_THREADS
poll_result = poll(self->ufds, self->ufd_len, timeout);
- Py_END_ALLOW_THREADS;
+ Py_END_ALLOW_THREADS
if (poll_result < 0) {
PyErr_SetFromErrno(SelectError);
@@ -646,6 +650,339 @@
#endif /* HAVE_POLL */
+#ifdef HAVE_EPOLL
+/* epoll support
+ */
+
+typedef struct {
+ PyObject_HEAD
+ int epfd;
+} PyEpoll_Object;
+
+static PyTypeObject PyEpoll_Type;
+#define PyEpoll_CHECK(op) (PyObject_TypeCheck((op), &PyEpoll_Type))
+
+static PyObject *
+pyepoll_err_closed(void)
+{
+ PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll fd");
+ return NULL;
+}
+
+static int
+pyepoll_internal_close(PyEpoll_Object *self)
+{
+ int save_errno = 0;
+ if (self->epfd >= 0) {
+ int epfd = self->epfd;
+ self->epfd = -1;
+ Py_BEGIN_ALLOW_THREADS
+ if (close(epfd) < 0)
+ save_errno = errno;
+ Py_END_ALLOW_THREADS
+ }
+ return save_errno;
+}
+
+static PyObject *
+pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyEpoll_Object *self;
+ int size;
+ static char *kwlist[] = {"size", NULL};
+
+ assert(type != NULL && type->tp_alloc != NULL);
+
+ self = (PyEpoll_Object *) type->tp_alloc(type, 0);
+ if (self == NULL)
+ return NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:epoll", kwlist, &size))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ self->epfd = epoll_create(size);
+ Py_END_ALLOW_THREADS
+ if (self->epfd < 0) {
+ Py_DECREF(self);
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ return (PyObject *)self;
+}
+
+static void
+pyepoll_dealloc(PyEpoll_Object *self)
+{
+ (void)pyepoll_internal_close(self);
+}
+
+static PyObject*
+pyepoll_close(PyEpoll_Object *self)
+{
+ errno = pyepoll_internal_close(self);
+ if (errno < 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(pyepoll_close_doc,
+"close() -> None\n\
+\n\
+Close the epoll control file descriptor. Further operations on the epoll\n\
+object will raise an exception.");
+
+static PyObject*
+pyepoll_get_closed(PyEpoll_Object *self)
+{
+ if (self->epfd < 0)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+static PyObject*
+pyepoll_fileno(PyEpoll_Object *self)
+{
+ if (self->epfd < 0)
+ return pyepoll_err_closed();
+ return PyLong_FromLong((long)self->epfd);
+}
+
+PyDoc_STRVAR(pyepoll_fileno_doc,
+"fileno() -> int\n\
+\n\
+Return the epoll control file descriptor.");
+
+static PyObject *
+pyepoll_internal_ctl(int epfd, int op, int fd, unsigned int events)
+{
+ struct epoll_event ev;
+ int result;
+
+ if (epfd < 0)
+ return pyepoll_err_closed();
+
+ switch(op) {
+ case EPOLL_CTL_ADD:
+ case EPOLL_CTL_MOD:
+ ev.events = events;
+ ev.data.fd = fd;
+ Py_BEGIN_ALLOW_THREADS
+ result = epoll_ctl(epfd, op, fd, &ev);
+ Py_END_ALLOW_THREADS
+ break;
+ case EPOLL_CTL_DEL:
+ /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL
+ * operation required a non-NULL pointer in event, even
+ * though this argument is ignored. */
+ Py_BEGIN_ALLOW_THREADS
+ result = epoll_ctl(epfd, op, fd, &ev);
+ Py_END_ALLOW_THREADS
+ break;
+ default:
+ result = -1;
+ errno = EINVAL;
+ }
+
+ if (result < 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pyepoll_register(PyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+ int fd;
+ unsigned int events = EPOLLIN | EPOLLOUT | EPOLLPRI;
+ static char *kwlist[] = {"fd", "eventmask", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|I:control", kwlist,
+ &fd, &events))
+ return NULL;
+ return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, fd, events);
+}
+
+PyDoc_STRVAR(pyepoll_register_doc,
+"register(fd[, eventmask]) -> None\n\
+\n\
+fd is the target file descriptor of the operation\n\
+events is a bit set composed of the various EPOLL constants, the default\n\
+is EPOLL_IN | EPOLL_OUT | EPOLL_PRI.\n\
+\n\
+The epoll interface supports all file descriptors that support poll.");
+
+static PyObject *
+pyepoll_modify(PyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+ int fd;
+ unsigned int events;
+ static char *kwlist[] = {"fd", "eventmask", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "iI:control", kwlist,
+ &fd, &events))
+ return NULL;
+ return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, fd, events);
+}
+
+PyDoc_STRVAR(pyepoll_modify_doc,
+"modify(fd, eventmask) -> None\n\
+\n\
+fd is the target file descriptor of the operation\n\
+events is a bit set composed of the various EPOLL constants");
+
+static PyObject *
+pyepoll_unregister(PyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+ int fd;
+ static char *kwlist[] = {"fd", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:control", kwlist,
+ &fd))
+ return NULL;
+ return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, fd, 0);
+}
+
+PyDoc_STRVAR(pyepoll_unregister_doc,
+"unregister(fd) -> None\n\
+\n\
+fd is the target file descriptor of the operation.");
+
+static PyObject *
+pyepoll_wait(PyEpoll_Object *self, PyObject *args, PyObject *kwds)
+{
+ int timeout, nfds, maxevents, size, i;
+ struct epoll_event *evs;
+ PyObject *elist = NULL, *etuple = NULL;
+ static char *kwlist[] = {"maxevents", "timeout", NULL};
+
+ if (self->epfd < 0)
+ return pyepoll_err_closed();
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ii:wait", kwlist,
+ &maxevents, &timeout))
+ return NULL;
+
+ size = maxevents * sizeof(struct epoll_event);
+ evs = (struct epoll_event*) PyMem_Malloc(size);
+ if (evs == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "failed to allocate memory for events");
+ return NULL;
+ }
+ memset(evs, 0, size);
+
+ Py_BEGIN_ALLOW_THREADS
+ nfds = epoll_wait(self->epfd, evs, maxevents, timeout);
+ Py_END_ALLOW_THREADS
+ if (nfds < 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ goto error;
+ }
+
+ elist = PyList_New(nfds);
+ if (elist == NULL) {
+ goto error;
+ }
+
+ for (i = 0; i < nfds; i++) {
+ etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events);
+ if (etuple == NULL) {
+ goto error;
+ }
+ PyList_SET_ITEM(elist, i, etuple);
+ }
+
+ if (0) {
+ error:
+ Py_CLEAR(elist);
+ Py_XDECREF(etuple);
+ }
+ PyMem_Free(evs);
+ return elist;
+}
+
+PyDoc_STRVAR(pyepoll_wait_doc,
+"wait(maxevents, timeout) -> [(fd, events), (...)]\n\
+\n\
+Wait for events on the epoll file descriptor for a maximum time of timeout\n\
+milliseconds. Up to maxevents are returned to the caller.");
+
+static PyMethodDef pyepoll_methods[] = {
+ {"close", (PyCFunction)pyepoll_close, METH_NOARGS,
+ pyepoll_close_doc},
+ {"fileno", (PyCFunction)pyepoll_fileno, METH_NOARGS,
+ pyepoll_fileno_doc},
+ {"modify", (PyCFunction)pyepoll_modify,
+ METH_VARARGS | METH_KEYWORDS, pyepoll_modify_doc},
+ {"register", (PyCFunction)pyepoll_register,
+ METH_VARARGS | METH_KEYWORDS, pyepoll_register_doc},
+ {"unregister", (PyCFunction)pyepoll_unregister,
+ METH_VARARGS | METH_KEYWORDS, pyepoll_unregister_doc},
+ {"wait", (PyCFunction)pyepoll_wait,
+ METH_VARARGS | METH_KEYWORDS, pyepoll_wait_doc},
+ {NULL, NULL},
+};
+
+static PyGetSetDef pyepoll_getsetlist[] = {
+ {"closed", (getter)pyepoll_get_closed, NULL,
+ "True if the epoll handler is closed"},
+ {0},
+};
+
+PyDoc_STRVAR(pyepoll_doc,
+"select.epoll(sizehint)\n\
+\n\
+Returns an epolling object");
+
+static PyTypeObject PyEpoll_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "select.epoll", /* tp_name */
+ sizeof(PyEpoll_Object), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)pyepoll_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ pyepoll_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ pyepoll_methods, /* tp_methods */
+ 0, /* tp_members */
+ pyepoll_getsetlist, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ pyepoll_new, /* tp_new */
+ 0, /* tp_free */
+};
+
+#endif /* HAVE_EPOLL */
+
PyDoc_STRVAR(select_doc,
"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
\n\
@@ -730,4 +1067,32 @@
#endif
}
#endif /* HAVE_POLL */
+#ifdef HAVE_EPOLL
+ Py_TYPE(&PyEpoll_Type) = &PyType_Type;
+ if (PyType_Ready(&PyEpoll_Type) < 0)
+ return;
+ PyModule_AddObject(m, "epoll", (PyObject *) &PyEpoll_Type);
+
+ PyModule_AddIntConstant(m, "EPOLL_IN", EPOLLIN);
+ PyModule_AddIntConstant(m, "EPOLL_OUT", EPOLLOUT);
+ PyModule_AddIntConstant(m, "EPOLL_PRI", EPOLLPRI);
+ PyModule_AddIntConstant(m, "EPOLL_ERR", EPOLLERR);
+ PyModule_AddIntConstant(m, "EPOLL_HUP", EPOLLHUP);
+ PyModule_AddIntConstant(m, "EPOLL_ET", EPOLLET);
+#ifdef EPOLLONESHOT
+ /* Kernel 2.6.2+ */
+ PyModule_AddIntConstant(m, "EPOLL_ONESHOT", EPOLLONESHOT);
+#endif
+ /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */
+ PyModule_AddIntConstant(m, "EPOLL_RDNORM", EPOLLRDNORM);
+ PyModule_AddIntConstant(m, "EPOLL_RDBAND", EPOLLRDBAND);
+ PyModule_AddIntConstant(m, "EPOLL_WRNORM", EPOLLWRNORM);
+ PyModule_AddIntConstant(m, "EPOLL_WRBAND", EPOLLWRBAND);
+ PyModule_AddIntConstant(m, "EPOLL_MSG", EPOLLMSG);
+
+ PyModule_AddIntConstant(m, "EPOLL_CTL_ADD", EPOLL_CTL_ADD);
+ PyModule_AddIntConstant(m, "EPOLL_CTL_MOD", EPOLL_CTL_MOD);
+ PyModule_AddIntConstant(m, "EPOLL_CTL_DEL", EPOLL_CTL_DEL);
+
+#endif /* HAVE_EPOLL */
}
Index: pyconfig.h.in
===================================================================
--- pyconfig.h.in (Revision 59566)
+++ pyconfig.h.in (Arbeitskopie)
@@ -138,6 +138,9 @@
/* Defined when any dynamic module loading is enabled. */
#undef HAVE_DYNAMIC_LOADING
+/* Define if you have the 'epoll' functions. */
+#undef HAVE_EPOLL
+
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
@@ -612,6 +615,9 @@
*/
#undef HAVE_SYS_DIR_H
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
@@ -1040,4 +1046,3 @@
#endif /*Py_PYCONFIG_H*/
-
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com