Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 113 lines (98 sloc) 3.015 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
/*
* 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 <string.h>
#include <sys/epoll.h>

#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);
}
Something went wrong with that request. Please try again.