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