Created
August 22, 2025 04:00
-
-
Save Vizonex/faa4b16ed4d56e3b74cca8e35778f406 to your computer and use it in GitHub Desktop.
_epoll.pyx Original 2006 Twisted source code I have saved a copy for archiving purposes since it is a historical artifact to helping shape CPython's selectmodule epoll system. It may or may not run correctly and I have uploaded it for viewing purposes only.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Copyright (c) 2001-2006 Twisted Matrix Laboratories. | |
| # See LICENSE for details. | |
| """ | |
| Interface to epoll I/O event notification facility. | |
| """ | |
| # NOTE: The version of Pyrex you are using probably _does not work_ with | |
| # Python 2.5. If you need to recompile this file, _make sure you are using | |
| # a version of Pyrex which works with Python 2.5_. I am using 0.9.4.1 from | |
| # <http://codespeak.net/svn/lxml/pyrex/>. -exarkun | |
| cdef extern from "stdio.h": | |
| cdef extern void *malloc(int) | |
| cdef extern void free(void *) | |
| cdef extern int close(int) | |
| cdef extern from "errno.h": | |
| cdef extern int errno | |
| cdef extern char *strerror(int) | |
| cdef extern from "string.h": | |
| cdef extern void *memset(void* s, int c, int n) | |
| cdef extern from "stdint.h": | |
| ctypedef unsigned long uint32_t | |
| ctypedef unsigned long long uint64_t | |
| cdef extern from "sys/epoll.h": | |
| cdef enum: | |
| EPOLL_CTL_ADD = 1 | |
| EPOLL_CTL_DEL = 2 | |
| EPOLL_CTL_MOD = 3 | |
| cdef enum EPOLL_EVENTS: | |
| EPOLLIN = 0x001 | |
| EPOLLPRI = 0x002 | |
| EPOLLOUT = 0x004 | |
| EPOLLRDNORM = 0x040 | |
| EPOLLRDBAND = 0x080 | |
| EPOLLWRNORM = 0x100 | |
| EPOLLWRBAND = 0x200 | |
| EPOLLMSG = 0x400 | |
| EPOLLERR = 0x008 | |
| EPOLLHUP = 0x010 | |
| EPOLLET = (1 << 31) | |
| ctypedef union epoll_data_t: | |
| void *ptr | |
| int fd | |
| uint32_t u32 | |
| uint64_t u64 | |
| cdef struct epoll_event: | |
| uint32_t events | |
| epoll_data_t data | |
| int epoll_create(int size) | |
| int epoll_ctl(int epfd, int op, int fd, epoll_event *event) | |
| int epoll_wait(int epfd, epoll_event *events, int maxevents, int timeout) | |
| cdef extern from "Python.h": | |
| ctypedef struct PyThreadState | |
| cdef extern PyThreadState *PyEval_SaveThread() | |
| cdef extern void PyEval_RestoreThread(PyThreadState*) | |
| cdef class epoll: | |
| """ | |
| Represent a set of file descriptors being monitored for events. | |
| """ | |
| cdef int fd | |
| cdef int initialized | |
| def __init__(self, int size): | |
| self.fd = epoll_create(size) | |
| if self.fd == -1: | |
| raise IOError(errno, strerror(errno)) | |
| self.initialized = 1 | |
| def __dealloc__(self): | |
| if self.initialized: | |
| close(self.fd) | |
| self.initialized = 0 | |
| def close(self): | |
| """ | |
| Close the epoll file descriptor. | |
| """ | |
| if self.initialized: | |
| if close(self.fd) == -1: | |
| raise IOError(errno, strerror(errno)) | |
| self.initialized = 0 | |
| def fileno(self): | |
| """ | |
| Return the epoll file descriptor number. | |
| """ | |
| return self.fd | |
| def _control(self, int op, int fd, int events): | |
| """ | |
| Modify the monitored state of a particular file descriptor. | |
| Wrap epoll_ctl(2). | |
| @type op: C{int} | |
| @param op: One of CTL_ADD, CTL_DEL, or CTL_MOD | |
| @type fd: C{int} | |
| @param fd: File descriptor to modify | |
| @type events: C{int} | |
| @param events: A bit set of IN, OUT, PRI, ERR, HUP, and ET. | |
| @raise IOError: Raised if the underlying epoll_ctl() call fails. | |
| """ | |
| cdef int result | |
| cdef epoll_event evt | |
| evt.events = events | |
| evt.data.fd = fd | |
| result = epoll_ctl(self.fd, op, fd, &evt) | |
| if result == -1: | |
| raise IOError(errno, strerror(errno)) | |
| def wait(self, unsigned int maxevents, int timeout): | |
| """ | |
| Wait for an I/O event, wrap epoll_wait(2). | |
| @type maxevents: C{int} | |
| @param maxevents: Maximum number of events returned. | |
| @type timeout: C{int} | |
| @param timeout: Maximum time waiting for events. 0 makes it return | |
| immediately whereas -1 makes it wait indefinitely. | |
| @raise IOError: Raised if the underlying epoll_wait() call fails. | |
| """ | |
| cdef epoll_event *events | |
| cdef int result | |
| cdef int nbytes | |
| cdef int fd | |
| cdef PyThreadState *_save | |
| nbytes = sizeof(epoll_event) * maxevents | |
| events = <epoll_event*>malloc(nbytes) | |
| memset(events, 0, nbytes) | |
| try: | |
| fd = self.fd | |
| _save = PyEval_SaveThread() | |
| result = epoll_wait(fd, events, maxevents, timeout) | |
| PyEval_RestoreThread(_save) | |
| if result == -1: | |
| raise IOError(errno, strerror(errno)) | |
| results = [] | |
| for i from 0 <= i < result: | |
| results.append((events[i].data.fd, <int>events[i].events)) | |
| return results | |
| finally: | |
| free(events) | |
| CTL_ADD = EPOLL_CTL_ADD | |
| CTL_DEL = EPOLL_CTL_DEL | |
| CTL_MOD = EPOLL_CTL_MOD | |
| IN = EPOLLIN | |
| OUT = EPOLLOUT | |
| PRI = EPOLLPRI | |
| ERR = EPOLLERR | |
| HUP = EPOLLHUP | |
| ET = EPOLLET | |
| RDNORM = EPOLLRDNORM | |
| RDBAND = EPOLLRDBAND | |
| WRNORM = EPOLLWRNORM | |
| WRBAND = EPOLLWRBAND | |
| MSG = EPOLLMSG | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment