]> arthur.barton.de Git - bup.git/blob - lib/tornado/epoll.c
Always publish (l)utimes in helpers when available and fix type conversions.
[bup.git] / lib / tornado / epoll.c
1 /*
2  * Copyright 2009 Facebook
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may
5  * not use this file except in compliance with the License. You may obtain
6  * a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16
17 #include "Python.h"
18 #include <string.h>
19 #include <sys/epoll.h>
20
21 #define MAX_EVENTS 24
22
23 /*
24  * Simple wrapper around epoll_create.
25  */
26 static PyObject* _epoll_create(void) {
27     int fd = epoll_create(MAX_EVENTS);
28     if (fd == -1) {
29         PyErr_SetFromErrno(PyExc_Exception);
30         return NULL;
31     }
32
33     return PyInt_FromLong(fd);
34 }
35
36 /*
37  * Simple wrapper around epoll_ctl. We throw an exception if the call fails
38  * rather than returning the error code since it is an infrequent (and likely
39  * catastrophic) event when it does happen.
40  */
41 static PyObject* _epoll_ctl(PyObject* self, PyObject* args) {
42     int epfd, op, fd, events;
43     struct epoll_event event;
44
45     if (!PyArg_ParseTuple(args, "iiiI", &epfd, &op, &fd, &events)) {
46         return NULL;
47     }
48
49     memset(&event, 0, sizeof(event));
50     event.events = events;
51     event.data.fd = fd;
52     if (epoll_ctl(epfd, op, fd, &event) == -1) {
53         PyErr_SetFromErrno(PyExc_OSError);
54         return NULL;
55     }
56
57     Py_INCREF(Py_None);
58     return Py_None;
59 }
60
61 /*
62  * Simple wrapper around epoll_wait. We return None if the call times out and
63  * throw an exception if an error occurs. Otherwise, we return a list of
64  * (fd, event) tuples.
65  */
66 static PyObject* _epoll_wait(PyObject* self, PyObject* args) {
67     struct epoll_event events[MAX_EVENTS];
68     int epfd, timeout, num_events, i;
69     PyObject* list;
70     PyObject* tuple;
71
72     if (!PyArg_ParseTuple(args, "ii", &epfd, &timeout)) {
73         return NULL;
74     }
75
76     Py_BEGIN_ALLOW_THREADS
77     num_events = epoll_wait(epfd, events, MAX_EVENTS, timeout);
78     Py_END_ALLOW_THREADS
79     if (num_events == -1) {
80         PyErr_SetFromErrno(PyExc_Exception);
81         return NULL;
82     }
83
84     list = PyList_New(num_events);
85     for (i = 0; i < num_events; i++) {
86         tuple = PyTuple_New(2);
87         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(events[i].data.fd));
88         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(events[i].events));
89         PyList_SET_ITEM(list, i, tuple);
90     }
91     return list;
92 }
93
94 /*
95  * Our method declararations
96  */
97 static PyMethodDef kEpollMethods[] = {
98   {"epoll_create", (PyCFunction)_epoll_create, METH_NOARGS,
99    "Create an epoll file descriptor"},
100   {"epoll_ctl", _epoll_ctl, METH_VARARGS,
101    "Control an epoll file descriptor"},
102   {"epoll_wait", _epoll_wait, METH_VARARGS,
103    "Wait for events on an epoll file descriptor"},
104   {NULL, NULL, 0, NULL}
105 };
106
107 /*
108  * Module initialization
109  */
110 PyMODINIT_FUNC initepoll(void) {
111     Py_InitModule("epoll", kEpollMethods);
112 }