/* * Copyright 2009 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ #include "Python.h" #include #include #define MAX_EVENTS 24 /* * Simple wrapper around epoll_create. */ static PyObject* _epoll_create(void) { int fd = epoll_create(MAX_EVENTS); if (fd == -1) { PyErr_SetFromErrno(PyExc_Exception); return NULL; } return PyInt_FromLong(fd); } /* * Simple wrapper around epoll_ctl. We throw an exception if the call fails * rather than returning the error code since it is an infrequent (and likely * catastrophic) event when it does happen. */ static PyObject* _epoll_ctl(PyObject* self, PyObject* args) { int epfd, op, fd, events; struct epoll_event event; if (!PyArg_ParseTuple(args, "iiiI", &epfd, &op, &fd, &events)) { return NULL; } memset(&event, 0, sizeof(event)); event.events = events; event.data.fd = fd; if (epoll_ctl(epfd, op, fd, &event) == -1) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } Py_INCREF(Py_None); return Py_None; } /* * Simple wrapper around epoll_wait. We return None if the call times out and * throw an exception if an error occurs. Otherwise, we return a list of * (fd, event) tuples. */ static PyObject* _epoll_wait(PyObject* self, PyObject* args) { struct epoll_event events[MAX_EVENTS]; int epfd, timeout, num_events, i; PyObject* list; PyObject* tuple; if (!PyArg_ParseTuple(args, "ii", &epfd, &timeout)) { return NULL; } Py_BEGIN_ALLOW_THREADS num_events = epoll_wait(epfd, events, MAX_EVENTS, timeout); Py_END_ALLOW_THREADS if (num_events == -1) { PyErr_SetFromErrno(PyExc_Exception); return NULL; } list = PyList_New(num_events); for (i = 0; i < num_events; i++) { tuple = PyTuple_New(2); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(events[i].data.fd)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(events[i].events)); PyList_SET_ITEM(list, i, tuple); } return list; } /* * Our method declararations */ static PyMethodDef kEpollMethods[] = { {"epoll_create", (PyCFunction)_epoll_create, METH_NOARGS, "Create an epoll file descriptor"}, {"epoll_ctl", _epoll_ctl, METH_VARARGS, "Control an epoll file descriptor"}, {"epoll_wait", _epoll_wait, METH_VARARGS, "Wait for events on an epoll file descriptor"}, {NULL, NULL, 0, NULL} }; /* * Module initialization */ PyMODINIT_FUNC initepoll(void) { Py_InitModule("epoll", kEpollMethods); }