1 #include <Python.h>
2 #include <ev.h>
3 
4 typedef struct libevwrapper_Loop {
5     PyObject_HEAD
6     struct ev_loop *loop;
7 } libevwrapper_Loop;
8 
9 static void
Loop_dealloc(libevwrapper_Loop * self)10 Loop_dealloc(libevwrapper_Loop *self) {
11     ev_loop_destroy(self->loop);
12     Py_TYPE(self)->tp_free((PyObject *)self);
13 };
14 
15 static PyObject*
Loop_new(PyTypeObject * type,PyObject * args,PyObject * kwds)16 Loop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
17     libevwrapper_Loop *self;
18 
19     self = (libevwrapper_Loop *)type->tp_alloc(type, 0);
20     if (self != NULL) {
21         self->loop = ev_loop_new(EVBACKEND_SELECT);
22         if (!self->loop) {
23             PyErr_SetString(PyExc_Exception, "Error getting new ev loop");
24             Py_DECREF(self);
25             return NULL;
26         }
27     }
28     return (PyObject *)self;
29 };
30 
31 static int
Loop_init(libevwrapper_Loop * self,PyObject * args,PyObject * kwds)32 Loop_init(libevwrapper_Loop *self, PyObject *args, PyObject *kwds) {
33     if (!PyArg_ParseTuple(args, "")) {
34         PyErr_SetString(PyExc_TypeError, "Loop.__init__() takes no arguments");
35         return -1;
36     }
37     return 0;
38 };
39 
40 static PyObject *
Loop_start(libevwrapper_Loop * self,PyObject * args)41 Loop_start(libevwrapper_Loop *self, PyObject *args) {
42     Py_BEGIN_ALLOW_THREADS
43     ev_run(self->loop, 0);
44     Py_END_ALLOW_THREADS
45     Py_RETURN_NONE;
46 };
47 
48 static PyObject *
Loop_unref(libevwrapper_Loop * self,PyObject * args)49 Loop_unref(libevwrapper_Loop *self, PyObject *args) {
50     ev_unref(self->loop);
51     Py_RETURN_NONE;
52 }
53 
54 static PyMethodDef Loop_methods[] = {
55     {"start", (PyCFunction)Loop_start, METH_NOARGS, "Start the event loop"},
56     {"unref", (PyCFunction)Loop_unref, METH_NOARGS, "Unrefrence the event loop"},
57     {NULL} /* Sentinel */
58 };
59 
60 static
61 PyTypeObject libevwrapper_LoopType = {
62     PyVarObject_HEAD_INIT(NULL, 0)
63     "cassandra.io.libevwrapper.Loop",/*tp_name*/
64     sizeof(libevwrapper_Loop),       /*tp_basicsize*/
65     0,                               /*tp_itemsize*/
66     (destructor)Loop_dealloc,        /*tp_dealloc*/
67     0,                               /*tp_print*/
68     0,                               /*tp_getattr*/
69     0,                               /*tp_setattr*/
70     0,                               /*tp_compare*/
71     0,                               /*tp_repr*/
72     0,                               /*tp_as_number*/
73     0,                               /*tp_as_sequence*/
74     0,                               /*tp_as_mapping*/
75     0,                               /*tp_hash */
76     0,                               /*tp_call*/
77     0,                               /*tp_str*/
78     0,                               /*tp_getattro*/
79     0,                               /*tp_setattro*/
80     0,                               /*tp_as_buffer*/
81     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
82     "Loop objects",                  /* tp_doc */
83     0,                               /* tp_traverse */
84     0,                               /* tp_clear */
85     0,                               /* tp_richcompare */
86     0,                               /* tp_weaklistoffset */
87     0,                               /* tp_iter */
88     0,                               /* tp_iternext */
89     Loop_methods,                    /* tp_methods */
90     0,                               /* tp_members */
91     0,                               /* tp_getset */
92     0,                               /* tp_base */
93     0,                               /* tp_dict */
94     0,                               /* tp_descr_get */
95     0,                               /* tp_descr_set */
96     0,                               /* tp_dictoffset */
97     (initproc)Loop_init,             /* tp_init */
98     0,                               /* tp_alloc */
99     Loop_new,                        /* tp_new */
100 };
101 
102 typedef struct libevwrapper_IO {
103     PyObject_HEAD
104     struct ev_io io;
105     struct libevwrapper_Loop *loop;
106     PyObject *callback;
107 } libevwrapper_IO;
108 
109 static void
IO_dealloc(libevwrapper_IO * self)110 IO_dealloc(libevwrapper_IO *self) {
111     Py_XDECREF(self->loop);
112     Py_XDECREF(self->callback);
113     Py_TYPE(self)->tp_free((PyObject *)self);
114 };
115 
io_callback(struct ev_loop * loop,ev_io * watcher,int revents)116 static void io_callback(struct ev_loop *loop, ev_io *watcher, int revents) {
117     libevwrapper_IO *self = watcher->data;
118     PyObject *result;
119     PyGILState_STATE gstate = PyGILState_Ensure();
120     if (revents & EV_ERROR && errno) {
121         result = PyObject_CallFunction(self->callback, "Obi", self, revents, errno);
122     } else {
123         result = PyObject_CallFunction(self->callback, "Ob", self, revents);
124     }
125     if (!result) {
126         PyErr_WriteUnraisable(self->callback);
127     }
128     Py_XDECREF(result);
129     PyGILState_Release(gstate);
130 };
131 
132 static int
IO_init(libevwrapper_IO * self,PyObject * args,PyObject * kwds)133 IO_init(libevwrapper_IO *self, PyObject *args, PyObject *kwds) {
134     PyObject *socket;
135     PyObject *callback;
136     PyObject *loop;
137     int io_flags = 0, fd = -1;
138     struct ev_io *io = NULL;
139 
140     if (!PyArg_ParseTuple(args, "OiOO", &socket, &io_flags, &loop, &callback)) {
141         return -1;
142     }
143 
144     if (loop) {
145         Py_INCREF(loop);
146         self->loop = (libevwrapper_Loop *)loop;
147     }
148 
149     if (callback) {
150         if (!PyCallable_Check(callback)) {
151             PyErr_SetString(PyExc_TypeError, "callback parameter must be callable");
152             Py_XDECREF(loop);
153             return -1;
154         }
155         Py_INCREF(callback);
156         self->callback = callback;
157     }
158 
159     fd = PyObject_AsFileDescriptor(socket);
160     if (fd == -1) {
161         PyErr_SetString(PyExc_TypeError, "unable to get file descriptor from socket");
162         Py_XDECREF(callback);
163         Py_XDECREF(loop);
164         return -1;
165     }
166     io = &(self->io);
167     ev_io_init(io, io_callback, fd, io_flags);
168     self->io.data = self;
169     return 0;
170 }
171 
172 static PyObject*
IO_start(libevwrapper_IO * self,PyObject * args)173 IO_start(libevwrapper_IO *self, PyObject *args) {
174     ev_io_start(self->loop->loop, &self->io);
175     Py_RETURN_NONE;
176 }
177 
178 static PyObject*
IO_stop(libevwrapper_IO * self,PyObject * args)179 IO_stop(libevwrapper_IO *self, PyObject *args) {
180     ev_io_stop(self->loop->loop, &self->io);
181     Py_RETURN_NONE;
182 }
183 
184 static PyObject*
IO_is_active(libevwrapper_IO * self,PyObject * args)185 IO_is_active(libevwrapper_IO *self, PyObject *args) {
186     struct ev_io *io = &(self->io);
187     return PyBool_FromLong(ev_is_active(io));
188 }
189 
190 static PyObject*
IO_is_pending(libevwrapper_IO * self,PyObject * args)191 IO_is_pending(libevwrapper_IO *self, PyObject *args) {
192     struct ev_io *io = &(self->io);
193     return PyBool_FromLong(ev_is_pending(io));
194 }
195 
196 static PyMethodDef IO_methods[] = {
197     {"start", (PyCFunction)IO_start, METH_NOARGS, "Start the watcher"},
198     {"stop", (PyCFunction)IO_stop, METH_NOARGS, "Stop the watcher"},
199     {"is_active", (PyCFunction)IO_is_active, METH_NOARGS, "Is the watcher active?"},
200     {"is_pending", (PyCFunction)IO_is_pending, METH_NOARGS, "Is the watcher pending?"},
201     {NULL}  /* Sentinal */
202 };
203 
204 static PyTypeObject libevwrapper_IOType = {
205     PyVarObject_HEAD_INIT(NULL, 0)
206     "cassandra.io.libevwrapper.IO",  /*tp_name*/
207     sizeof(libevwrapper_IO),         /*tp_basicsize*/
208     0,                               /*tp_itemsize*/
209     (destructor)IO_dealloc,          /*tp_dealloc*/
210     0,                               /*tp_print*/
211     0,                               /*tp_getattr*/
212     0,                               /*tp_setattr*/
213     0,                               /*tp_compare*/
214     0,                               /*tp_repr*/
215     0,                               /*tp_as_number*/
216     0,                               /*tp_as_sequence*/
217     0,                               /*tp_as_mapping*/
218     0,                               /*tp_hash */
219     0,                               /*tp_call*/
220     0,                               /*tp_str*/
221     0,                               /*tp_getattro*/
222     0,                               /*tp_setattro*/
223     0,                               /*tp_as_buffer*/
224     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
225     "IO objects",                    /* tp_doc */
226     0,                               /* tp_traverse */
227     0,                               /* tp_clear */
228     0,                               /* tp_richcompare */
229     0,                               /* tp_weaklistoffset */
230     0,                               /* tp_iter */
231     0,                               /* tp_iternext */
232     IO_methods,                      /* tp_methods */
233     0,                               /* tp_members */
234     0,                               /* tp_getset */
235     0,                               /* tp_base */
236     0,                               /* tp_dict */
237     0,                               /* tp_descr_get */
238     0,                               /* tp_descr_set */
239     0,                               /* tp_dictoffset */
240     (initproc)IO_init,               /* tp_init */
241 };
242 
243 typedef struct libevwrapper_Async {
244     PyObject_HEAD
245     struct ev_async async;
246     struct libevwrapper_Loop *loop;
247 } libevwrapper_Async;
248 
249 static void
Async_dealloc(libevwrapper_Async * self)250 Async_dealloc(libevwrapper_Async *self) {
251     Py_XDECREF(self->loop);
252     Py_TYPE(self)->tp_free((PyObject *)self);
253 };
254 
async_callback(EV_P_ ev_async * watcher,int revents)255 static void async_callback(EV_P_ ev_async *watcher, int revents) {};
256 
257 static int
Async_init(libevwrapper_Async * self,PyObject * args,PyObject * kwds)258 Async_init(libevwrapper_Async *self, PyObject *args, PyObject *kwds) {
259     PyObject *loop;
260     static char *kwlist[] = {"loop", NULL};
261     struct ev_async *async = NULL;
262 
263     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &loop)) {
264         PyErr_SetString(PyExc_TypeError, "unable to get file descriptor from socket");
265         return -1;
266     }
267 
268     if (loop) {
269         Py_INCREF(loop);
270         self->loop = (libevwrapper_Loop *)loop;
271     } else {
272         return -1;
273     }
274     async = &(self->async);
275     ev_async_init(async, async_callback);
276     return 0;
277 };
278 
279 static PyObject *
Async_start(libevwrapper_Async * self,PyObject * args)280 Async_start(libevwrapper_Async *self, PyObject *args) {
281     ev_async_start(self->loop->loop, &self->async);
282     Py_RETURN_NONE;
283 }
284 
285 static PyObject *
Async_send(libevwrapper_Async * self,PyObject * args)286 Async_send(libevwrapper_Async *self, PyObject *args) {
287     ev_async_send(self->loop->loop, &self->async);
288     Py_RETURN_NONE;
289 };
290 
291 static PyMethodDef Async_methods[] = {
292     {"start", (PyCFunction)Async_start, METH_NOARGS, "Start the watcher"},
293     {"send", (PyCFunction)Async_send, METH_NOARGS, "Notify the event loop"},
294     {NULL} /* Sentinel */
295 };
296 
297 static PyTypeObject libevwrapper_AsyncType = {
298     PyVarObject_HEAD_INIT(NULL, 0)
299     "cassandra.io.libevwrapper.Async", /*tp_name*/
300     sizeof(libevwrapper_Async),      /*tp_basicsize*/
301     0,                               /*tp_itemsize*/
302     (destructor)Async_dealloc,       /*tp_dealloc*/
303     0,                               /*tp_print*/
304     0,                               /*tp_getattr*/
305     0,                               /*tp_setattr*/
306     0,                               /*tp_compare*/
307     0,                               /*tp_repr*/
308     0,                               /*tp_as_number*/
309     0,                               /*tp_as_sequence*/
310     0,                               /*tp_as_mapping*/
311     0,                               /*tp_hash */
312     0,                               /*tp_call*/
313     0,                               /*tp_str*/
314     0,                               /*tp_getattro*/
315     0,                               /*tp_setattro*/
316     0,                               /*tp_as_buffer*/
317     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
318     "Async objects",                 /* tp_doc */
319     0,                               /* tp_traverse */
320     0,                               /* tp_clear */
321     0,                               /* tp_richcompare */
322     0,                               /* tp_weaklistoffset */
323     0,                               /* tp_iter */
324     0,                               /* tp_iternext */
325     Async_methods,                   /* tp_methods */
326     0,                               /* tp_members */
327     0,                               /* tp_getset */
328     0,                               /* tp_base */
329     0,                               /* tp_dict */
330     0,                               /* tp_descr_get */
331     0,                               /* tp_descr_set */
332     0,                               /* tp_dictoffset */
333     (initproc)Async_init,            /* tp_init */
334 };
335 
336 typedef struct libevwrapper_Prepare {
337     PyObject_HEAD
338     struct ev_prepare prepare;
339     struct libevwrapper_Loop *loop;
340     PyObject *callback;
341 } libevwrapper_Prepare;
342 
343 static void
Prepare_dealloc(libevwrapper_Prepare * self)344 Prepare_dealloc(libevwrapper_Prepare *self) {
345     Py_XDECREF(self->loop);
346     Py_XDECREF(self->callback);
347     Py_TYPE(self)->tp_free((PyObject *)self);
348 }
349 
prepare_callback(struct ev_loop * loop,ev_prepare * watcher,int revents)350 static void prepare_callback(struct ev_loop *loop, ev_prepare *watcher, int revents) {
351     libevwrapper_Prepare *self = watcher->data;
352     PyObject *result = NULL;
353     PyGILState_STATE gstate;
354 
355     gstate = PyGILState_Ensure();
356     result = PyObject_CallFunction(self->callback, "O", self);
357     if (!result) {
358         PyErr_WriteUnraisable(self->callback);
359     }
360     Py_XDECREF(result);
361 
362     PyGILState_Release(gstate);
363 }
364 
365 static int
Prepare_init(libevwrapper_Prepare * self,PyObject * args,PyObject * kwds)366 Prepare_init(libevwrapper_Prepare *self, PyObject *args, PyObject *kwds) {
367     PyObject *callback;
368     PyObject *loop;
369     struct ev_prepare *prepare = NULL;
370 
371     if (!PyArg_ParseTuple(args, "OO", &loop, &callback)) {
372         return -1;
373     }
374 
375     if (loop) {
376         Py_INCREF(loop);
377         self->loop = (libevwrapper_Loop *)loop;
378     } else {
379         return -1;
380     }
381 
382     if (callback) {
383         if (!PyCallable_Check(callback)) {
384             PyErr_SetString(PyExc_TypeError, "callback parameter must be callable");
385             Py_XDECREF(loop);
386             return -1;
387         }
388         Py_INCREF(callback);
389         self->callback = callback;
390     }
391     prepare = &(self->prepare);
392     ev_prepare_init(prepare, prepare_callback);
393     self->prepare.data = self;
394     return 0;
395 }
396 
397 static PyObject *
Prepare_start(libevwrapper_Prepare * self,PyObject * args)398 Prepare_start(libevwrapper_Prepare *self, PyObject *args) {
399     ev_prepare_start(self->loop->loop, &self->prepare);
400     Py_RETURN_NONE;
401 }
402 
403 static PyObject *
Prepare_stop(libevwrapper_Prepare * self,PyObject * args)404 Prepare_stop(libevwrapper_Prepare *self, PyObject *args) {
405     ev_prepare_stop(self->loop->loop, &self->prepare);
406     Py_RETURN_NONE;
407 }
408 
409 static PyMethodDef Prepare_methods[] = {
410     {"start", (PyCFunction)Prepare_start, METH_NOARGS, "Start the Prepare watcher"},
411     {"stop", (PyCFunction)Prepare_stop, METH_NOARGS, "Stop the Prepare watcher"},
412     {NULL}  /* Sentinal */
413 };
414 
415 static PyTypeObject libevwrapper_PrepareType = {
416     PyVarObject_HEAD_INIT(NULL, 0)
417     "cassandra.io.libevwrapper.Prepare",  /*tp_name*/
418     sizeof(libevwrapper_Prepare),    /*tp_basicsize*/
419     0,                               /*tp_itemsize*/
420     (destructor)Prepare_dealloc,     /*tp_dealloc*/
421     0,                               /*tp_print*/
422     0,                               /*tp_getattr*/
423     0,                               /*tp_setattr*/
424     0,                               /*tp_compare*/
425     0,                               /*tp_repr*/
426     0,                               /*tp_as_number*/
427     0,                               /*tp_as_sequence*/
428     0,                               /*tp_as_mapping*/
429     0,                               /*tp_hash */
430     0,                               /*tp_call*/
431     0,                               /*tp_str*/
432     0,                               /*tp_getattro*/
433     0,                               /*tp_setattro*/
434     0,                               /*tp_as_buffer*/
435     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
436     "Prepare objects",               /* tp_doc */
437     0,                               /* tp_traverse */
438     0,                               /* tp_clear */
439     0,                               /* tp_richcompare */
440     0,                               /* tp_weaklistoffset */
441     0,                               /* tp_iter */
442     0,                               /* tp_iternext */
443     Prepare_methods,                 /* tp_methods */
444     0,                               /* tp_members */
445     0,                               /* tp_getset */
446     0,                               /* tp_base */
447     0,                               /* tp_dict */
448     0,                               /* tp_descr_get */
449     0,                               /* tp_descr_set */
450     0,                               /* tp_dictoffset */
451     (initproc)Prepare_init,          /* tp_init */
452 };
453 
454 typedef struct libevwrapper_Timer {
455     PyObject_HEAD
456     struct ev_timer timer;
457     struct libevwrapper_Loop *loop;
458     PyObject *callback;
459 } libevwrapper_Timer;
460 
461 static void
Timer_dealloc(libevwrapper_Timer * self)462 Timer_dealloc(libevwrapper_Timer *self) {
463     Py_XDECREF(self->loop);
464     Py_XDECREF(self->callback);
465     Py_TYPE(self)->tp_free((PyObject *)self);
466 }
467 
timer_callback(struct ev_loop * loop,ev_timer * watcher,int revents)468 static void timer_callback(struct ev_loop *loop, ev_timer *watcher, int revents) {
469     libevwrapper_Timer *self = watcher->data;
470 
471     PyObject *result = NULL;
472     PyGILState_STATE gstate;
473 
474     gstate = PyGILState_Ensure();
475     result = PyObject_CallFunction(self->callback, NULL);
476     if (!result) {
477         PyErr_WriteUnraisable(self->callback);
478     }
479     Py_XDECREF(result);
480 
481     PyGILState_Release(gstate);
482 }
483 
484 static int
Timer_init(libevwrapper_Timer * self,PyObject * args,PyObject * kwds)485 Timer_init(libevwrapper_Timer *self, PyObject *args, PyObject *kwds) {
486     PyObject *callback;
487     PyObject *loop;
488 
489     if (!PyArg_ParseTuple(args, "OO", &loop, &callback)) {
490         return -1;
491     }
492 
493     if (loop) {
494         Py_INCREF(loop);
495         self->loop = (libevwrapper_Loop *)loop;
496     } else {
497         return -1;
498     }
499 
500     if (callback) {
501         if (!PyCallable_Check(callback)) {
502             PyErr_SetString(PyExc_TypeError, "callback parameter must be callable");
503             Py_XDECREF(loop);
504             return -1;
505         }
506         Py_INCREF(callback);
507         self->callback = callback;
508     }
509     ev_init(&self->timer, timer_callback);
510     self->timer.data = self;
511     return 0;
512 }
513 
514 static PyObject *
Timer_start(libevwrapper_Timer * self,PyObject * args)515 Timer_start(libevwrapper_Timer *self, PyObject *args) {
516     double timeout;
517     if (!PyArg_ParseTuple(args, "d", &timeout)) {
518         return NULL;
519     }
520     /* some tiny non-zero number to avoid zero, and
521      make it run immediately for negative timeouts */
522     self->timer.repeat = fmax(timeout, 0.000000001);
523     ev_timer_again(self->loop->loop, &self->timer);
524     Py_RETURN_NONE;
525 }
526 
527 static PyObject *
Timer_stop(libevwrapper_Timer * self,PyObject * args)528 Timer_stop(libevwrapper_Timer *self, PyObject *args) {
529     ev_timer_stop(self->loop->loop, &self->timer);
530     Py_RETURN_NONE;
531 }
532 
533 static PyMethodDef Timer_methods[] = {
534     {"start", (PyCFunction)Timer_start, METH_VARARGS, "Start the Timer watcher"},
535     {"stop", (PyCFunction)Timer_stop, METH_NOARGS, "Stop the Timer watcher"},
536     {NULL}  /* Sentinal */
537 };
538 
539 static PyTypeObject libevwrapper_TimerType = {
540     PyVarObject_HEAD_INIT(NULL, 0)
541     "cassandra.io.libevwrapper.Timer",  /*tp_name*/
542     sizeof(libevwrapper_Timer),      /*tp_basicsize*/
543     0,                               /*tp_itemsize*/
544     (destructor)Timer_dealloc,       /*tp_dealloc*/
545     0,                               /*tp_print*/
546     0,                               /*tp_getattr*/
547     0,                               /*tp_setattr*/
548     0,                               /*tp_compare*/
549     0,                               /*tp_repr*/
550     0,                               /*tp_as_number*/
551     0,                               /*tp_as_sequence*/
552     0,                               /*tp_as_mapping*/
553     0,                               /*tp_hash */
554     0,                               /*tp_call*/
555     0,                               /*tp_str*/
556     0,                               /*tp_getattro*/
557     0,                               /*tp_setattro*/
558     0,                               /*tp_as_buffer*/
559     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
560     "Timer objects",                 /* tp_doc */
561     0,                               /* tp_traverse */
562     0,                               /* tp_clear */
563     0,                               /* tp_richcompare */
564     0,                               /* tp_weaklistoffset */
565     0,                               /* tp_iter */
566     0,                               /* tp_iternext */
567     Timer_methods,                   /* tp_methods */
568     0,                               /* tp_members */
569     0,                               /* tp_getset */
570     0,                               /* tp_base */
571     0,                               /* tp_dict */
572     0,                               /* tp_descr_get */
573     0,                               /* tp_descr_set */
574     0,                               /* tp_dictoffset */
575     (initproc)Timer_init,            /* tp_init */
576 };
577 
578 
579 static PyMethodDef module_methods[] = {
580     {NULL}  /* Sentinal */
581 };
582 
583 PyDoc_STRVAR(module_doc,
584 "libev wrapper methods");
585 
586 #if PY_MAJOR_VERSION >= 3
587 static struct PyModuleDef moduledef = {
588     PyModuleDef_HEAD_INIT,
589     "libevwrapper",
590     module_doc,
591     -1,
592     module_methods,
593     NULL,
594     NULL,
595     NULL,
596     NULL
597 };
598 
599 #define INITERROR return NULL
600 
601 PyObject *
PyInit_libevwrapper(void)602 PyInit_libevwrapper(void)
603 
604 # else
605 # define INITERROR return
606 
607 void
608 initlibevwrapper(void)
609 #endif
610 {
611     PyObject *module = NULL;
612 
613     if (PyType_Ready(&libevwrapper_LoopType) < 0)
614         INITERROR;
615 
616     libevwrapper_IOType.tp_new = PyType_GenericNew;
617     if (PyType_Ready(&libevwrapper_IOType) < 0)
618         INITERROR;
619 
620     libevwrapper_PrepareType.tp_new = PyType_GenericNew;
621     if (PyType_Ready(&libevwrapper_PrepareType) < 0)
622         INITERROR;
623 
624     libevwrapper_AsyncType.tp_new = PyType_GenericNew;
625     if (PyType_Ready(&libevwrapper_AsyncType) < 0)
626         INITERROR;
627 
628     libevwrapper_TimerType.tp_new = PyType_GenericNew;
629     if (PyType_Ready(&libevwrapper_TimerType) < 0)
630         INITERROR;
631 
632 # if PY_MAJOR_VERSION >= 3
633     module = PyModule_Create(&moduledef);
634 # else
635     module = Py_InitModule3("libevwrapper", module_methods, module_doc);
636 # endif
637 
638     if (module == NULL)
639         INITERROR;
640 
641     if (PyModule_AddIntConstant(module, "EV_READ", EV_READ) == -1)
642         INITERROR;
643     if (PyModule_AddIntConstant(module, "EV_WRITE", EV_WRITE) == -1)
644         INITERROR;
645     if (PyModule_AddIntConstant(module, "EV_ERROR", EV_ERROR) == -1)
646         INITERROR;
647 
648     Py_INCREF(&libevwrapper_LoopType);
649     if (PyModule_AddObject(module, "Loop", (PyObject *)&libevwrapper_LoopType) == -1)
650         INITERROR;
651 
652     Py_INCREF(&libevwrapper_IOType);
653     if (PyModule_AddObject(module, "IO", (PyObject *)&libevwrapper_IOType) == -1)
654         INITERROR;
655 
656     Py_INCREF(&libevwrapper_PrepareType);
657     if (PyModule_AddObject(module, "Prepare", (PyObject *)&libevwrapper_PrepareType) == -1)
658         INITERROR;
659 
660     Py_INCREF(&libevwrapper_AsyncType);
661     if (PyModule_AddObject(module, "Async", (PyObject *)&libevwrapper_AsyncType) == -1)
662         INITERROR;
663 
664     Py_INCREF(&libevwrapper_TimerType);
665     if (PyModule_AddObject(module, "Timer", (PyObject *)&libevwrapper_TimerType) == -1)
666         INITERROR;
667 
668     if (!PyEval_ThreadsInitialized()) {
669         PyEval_InitThreads();
670     }
671 
672 #if PY_MAJOR_VERSION >= 3
673     return module;
674 #endif
675 }
676