#include #include typedef struct libevwrapper_Loop { PyObject_HEAD struct ev_loop *loop; } libevwrapper_Loop; static void Loop_dealloc(libevwrapper_Loop *self) { ev_loop_destroy(self->loop); Py_TYPE(self)->tp_free((PyObject *)self); }; static PyObject* Loop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { libevwrapper_Loop *self; self = (libevwrapper_Loop *)type->tp_alloc(type, 0); if (self != NULL) { self->loop = ev_loop_new(EVBACKEND_SELECT); if (!self->loop) { PyErr_SetString(PyExc_Exception, "Error getting new ev loop"); Py_DECREF(self); return NULL; } } return (PyObject *)self; }; static int Loop_init(libevwrapper_Loop *self, PyObject *args, PyObject *kwds) { if (!PyArg_ParseTuple(args, "")) { PyErr_SetString(PyExc_TypeError, "Loop.__init__() takes no arguments"); return -1; } return 0; }; static PyObject * Loop_start(libevwrapper_Loop *self, PyObject *args) { Py_BEGIN_ALLOW_THREADS ev_run(self->loop, 0); Py_END_ALLOW_THREADS Py_RETURN_NONE; }; static PyObject * Loop_unref(libevwrapper_Loop *self, PyObject *args) { ev_unref(self->loop); Py_RETURN_NONE; } static PyMethodDef Loop_methods[] = { {"start", (PyCFunction)Loop_start, METH_NOARGS, "Start the event loop"}, {"unref", (PyCFunction)Loop_unref, METH_NOARGS, "Unrefrence the event loop"}, {NULL} /* Sentinel */ }; static PyTypeObject libevwrapper_LoopType = { PyVarObject_HEAD_INIT(NULL, 0) "cassandra.io.libevwrapper.Loop",/*tp_name*/ sizeof(libevwrapper_Loop), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Loop_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Loop objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Loop_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Loop_init, /* tp_init */ 0, /* tp_alloc */ Loop_new, /* tp_new */ }; typedef struct libevwrapper_IO { PyObject_HEAD struct ev_io io; struct libevwrapper_Loop *loop; PyObject *callback; } libevwrapper_IO; static void IO_dealloc(libevwrapper_IO *self) { Py_XDECREF(self->loop); Py_XDECREF(self->callback); Py_TYPE(self)->tp_free((PyObject *)self); }; static void io_callback(struct ev_loop *loop, ev_io *watcher, int revents) { libevwrapper_IO *self = watcher->data; PyObject *result; PyGILState_STATE gstate = PyGILState_Ensure(); if (revents & EV_ERROR && errno) { result = PyObject_CallFunction(self->callback, "Obi", self, revents, errno); } else { result = PyObject_CallFunction(self->callback, "Ob", self, revents); } if (!result) { PyErr_WriteUnraisable(self->callback); } Py_XDECREF(result); PyGILState_Release(gstate); }; static int IO_init(libevwrapper_IO *self, PyObject *args, PyObject *kwds) { PyObject *socket; PyObject *callback; PyObject *loop; int io_flags = 0, fd = -1; struct ev_io *io = NULL; if (!PyArg_ParseTuple(args, "OiOO", &socket, &io_flags, &loop, &callback)) { return -1; } if (loop) { Py_INCREF(loop); self->loop = (libevwrapper_Loop *)loop; } if (callback) { if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "callback parameter must be callable"); Py_XDECREF(loop); return -1; } Py_INCREF(callback); self->callback = callback; } fd = PyObject_AsFileDescriptor(socket); if (fd == -1) { PyErr_SetString(PyExc_TypeError, "unable to get file descriptor from socket"); Py_XDECREF(callback); Py_XDECREF(loop); return -1; } io = &(self->io); ev_io_init(io, io_callback, fd, io_flags); self->io.data = self; return 0; } static PyObject* IO_start(libevwrapper_IO *self, PyObject *args) { ev_io_start(self->loop->loop, &self->io); Py_RETURN_NONE; } static PyObject* IO_stop(libevwrapper_IO *self, PyObject *args) { ev_io_stop(self->loop->loop, &self->io); Py_RETURN_NONE; } static PyObject* IO_is_active(libevwrapper_IO *self, PyObject *args) { struct ev_io *io = &(self->io); return PyBool_FromLong(ev_is_active(io)); } static PyObject* IO_is_pending(libevwrapper_IO *self, PyObject *args) { struct ev_io *io = &(self->io); return PyBool_FromLong(ev_is_pending(io)); } static PyMethodDef IO_methods[] = { {"start", (PyCFunction)IO_start, METH_NOARGS, "Start the watcher"}, {"stop", (PyCFunction)IO_stop, METH_NOARGS, "Stop the watcher"}, {"is_active", (PyCFunction)IO_is_active, METH_NOARGS, "Is the watcher active?"}, {"is_pending", (PyCFunction)IO_is_pending, METH_NOARGS, "Is the watcher pending?"}, {NULL} /* Sentinal */ }; static PyTypeObject libevwrapper_IOType = { PyVarObject_HEAD_INIT(NULL, 0) "cassandra.io.libevwrapper.IO", /*tp_name*/ sizeof(libevwrapper_IO), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IO_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "IO objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IO_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)IO_init, /* tp_init */ }; typedef struct libevwrapper_Async { PyObject_HEAD struct ev_async async; struct libevwrapper_Loop *loop; } libevwrapper_Async; static void Async_dealloc(libevwrapper_Async *self) { Py_XDECREF(self->loop); Py_TYPE(self)->tp_free((PyObject *)self); }; static void async_callback(EV_P_ ev_async *watcher, int revents) {}; static int Async_init(libevwrapper_Async *self, PyObject *args, PyObject *kwds) { PyObject *loop; static char *kwlist[] = {"loop", NULL}; struct ev_async *async = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &loop)) { PyErr_SetString(PyExc_TypeError, "unable to get file descriptor from socket"); return -1; } if (loop) { Py_INCREF(loop); self->loop = (libevwrapper_Loop *)loop; } else { return -1; } async = &(self->async); ev_async_init(async, async_callback); return 0; }; static PyObject * Async_start(libevwrapper_Async *self, PyObject *args) { ev_async_start(self->loop->loop, &self->async); Py_RETURN_NONE; } static PyObject * Async_send(libevwrapper_Async *self, PyObject *args) { ev_async_send(self->loop->loop, &self->async); Py_RETURN_NONE; }; static PyMethodDef Async_methods[] = { {"start", (PyCFunction)Async_start, METH_NOARGS, "Start the watcher"}, {"send", (PyCFunction)Async_send, METH_NOARGS, "Notify the event loop"}, {NULL} /* Sentinel */ }; static PyTypeObject libevwrapper_AsyncType = { PyVarObject_HEAD_INIT(NULL, 0) "cassandra.io.libevwrapper.Async", /*tp_name*/ sizeof(libevwrapper_Async), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Async_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Async objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Async_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Async_init, /* tp_init */ }; typedef struct libevwrapper_Prepare { PyObject_HEAD struct ev_prepare prepare; struct libevwrapper_Loop *loop; PyObject *callback; } libevwrapper_Prepare; static void Prepare_dealloc(libevwrapper_Prepare *self) { Py_XDECREF(self->loop); Py_XDECREF(self->callback); Py_TYPE(self)->tp_free((PyObject *)self); } static void prepare_callback(struct ev_loop *loop, ev_prepare *watcher, int revents) { libevwrapper_Prepare *self = watcher->data; PyObject *result = NULL; PyGILState_STATE gstate; gstate = PyGILState_Ensure(); result = PyObject_CallFunction(self->callback, "O", self); if (!result) { PyErr_WriteUnraisable(self->callback); } Py_XDECREF(result); PyGILState_Release(gstate); } static int Prepare_init(libevwrapper_Prepare *self, PyObject *args, PyObject *kwds) { PyObject *callback; PyObject *loop; struct ev_prepare *prepare = NULL; if (!PyArg_ParseTuple(args, "OO", &loop, &callback)) { return -1; } if (loop) { Py_INCREF(loop); self->loop = (libevwrapper_Loop *)loop; } else { return -1; } if (callback) { if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "callback parameter must be callable"); Py_XDECREF(loop); return -1; } Py_INCREF(callback); self->callback = callback; } prepare = &(self->prepare); ev_prepare_init(prepare, prepare_callback); self->prepare.data = self; return 0; } static PyObject * Prepare_start(libevwrapper_Prepare *self, PyObject *args) { ev_prepare_start(self->loop->loop, &self->prepare); Py_RETURN_NONE; } static PyObject * Prepare_stop(libevwrapper_Prepare *self, PyObject *args) { ev_prepare_stop(self->loop->loop, &self->prepare); Py_RETURN_NONE; } static PyMethodDef Prepare_methods[] = { {"start", (PyCFunction)Prepare_start, METH_NOARGS, "Start the Prepare watcher"}, {"stop", (PyCFunction)Prepare_stop, METH_NOARGS, "Stop the Prepare watcher"}, {NULL} /* Sentinal */ }; static PyTypeObject libevwrapper_PrepareType = { PyVarObject_HEAD_INIT(NULL, 0) "cassandra.io.libevwrapper.Prepare", /*tp_name*/ sizeof(libevwrapper_Prepare), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Prepare_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Prepare objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Prepare_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Prepare_init, /* tp_init */ }; typedef struct libevwrapper_Timer { PyObject_HEAD struct ev_timer timer; struct libevwrapper_Loop *loop; PyObject *callback; } libevwrapper_Timer; static void Timer_dealloc(libevwrapper_Timer *self) { Py_XDECREF(self->loop); Py_XDECREF(self->callback); Py_TYPE(self)->tp_free((PyObject *)self); } static void timer_callback(struct ev_loop *loop, ev_timer *watcher, int revents) { libevwrapper_Timer *self = watcher->data; PyObject *result = NULL; PyGILState_STATE gstate; gstate = PyGILState_Ensure(); result = PyObject_CallFunction(self->callback, NULL); if (!result) { PyErr_WriteUnraisable(self->callback); } Py_XDECREF(result); PyGILState_Release(gstate); } static int Timer_init(libevwrapper_Timer *self, PyObject *args, PyObject *kwds) { PyObject *callback; PyObject *loop; if (!PyArg_ParseTuple(args, "OO", &loop, &callback)) { return -1; } if (loop) { Py_INCREF(loop); self->loop = (libevwrapper_Loop *)loop; } else { return -1; } if (callback) { if (!PyCallable_Check(callback)) { PyErr_SetString(PyExc_TypeError, "callback parameter must be callable"); Py_XDECREF(loop); return -1; } Py_INCREF(callback); self->callback = callback; } ev_init(&self->timer, timer_callback); self->timer.data = self; return 0; } static PyObject * Timer_start(libevwrapper_Timer *self, PyObject *args) { double timeout; if (!PyArg_ParseTuple(args, "d", &timeout)) { return NULL; } /* some tiny non-zero number to avoid zero, and make it run immediately for negative timeouts */ self->timer.repeat = fmax(timeout, 0.000000001); ev_timer_again(self->loop->loop, &self->timer); Py_RETURN_NONE; } static PyObject * Timer_stop(libevwrapper_Timer *self, PyObject *args) { ev_timer_stop(self->loop->loop, &self->timer); Py_RETURN_NONE; } static PyMethodDef Timer_methods[] = { {"start", (PyCFunction)Timer_start, METH_VARARGS, "Start the Timer watcher"}, {"stop", (PyCFunction)Timer_stop, METH_NOARGS, "Stop the Timer watcher"}, {NULL} /* Sentinal */ }; static PyTypeObject libevwrapper_TimerType = { PyVarObject_HEAD_INIT(NULL, 0) "cassandra.io.libevwrapper.Timer", /*tp_name*/ sizeof(libevwrapper_Timer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Timer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Timer objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Timer_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Timer_init, /* tp_init */ }; static PyMethodDef module_methods[] = { {NULL} /* Sentinal */ }; PyDoc_STRVAR(module_doc, "libev wrapper methods"); #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "libevwrapper", module_doc, -1, module_methods, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyObject * PyInit_libevwrapper(void) # else # define INITERROR return void initlibevwrapper(void) #endif { PyObject *module = NULL; if (PyType_Ready(&libevwrapper_LoopType) < 0) INITERROR; libevwrapper_IOType.tp_new = PyType_GenericNew; if (PyType_Ready(&libevwrapper_IOType) < 0) INITERROR; libevwrapper_PrepareType.tp_new = PyType_GenericNew; if (PyType_Ready(&libevwrapper_PrepareType) < 0) INITERROR; libevwrapper_AsyncType.tp_new = PyType_GenericNew; if (PyType_Ready(&libevwrapper_AsyncType) < 0) INITERROR; libevwrapper_TimerType.tp_new = PyType_GenericNew; if (PyType_Ready(&libevwrapper_TimerType) < 0) INITERROR; # if PY_MAJOR_VERSION >= 3 module = PyModule_Create(&moduledef); # else module = Py_InitModule3("libevwrapper", module_methods, module_doc); # endif if (module == NULL) INITERROR; if (PyModule_AddIntConstant(module, "EV_READ", EV_READ) == -1) INITERROR; if (PyModule_AddIntConstant(module, "EV_WRITE", EV_WRITE) == -1) INITERROR; if (PyModule_AddIntConstant(module, "EV_ERROR", EV_ERROR) == -1) INITERROR; Py_INCREF(&libevwrapper_LoopType); if (PyModule_AddObject(module, "Loop", (PyObject *)&libevwrapper_LoopType) == -1) INITERROR; Py_INCREF(&libevwrapper_IOType); if (PyModule_AddObject(module, "IO", (PyObject *)&libevwrapper_IOType) == -1) INITERROR; Py_INCREF(&libevwrapper_PrepareType); if (PyModule_AddObject(module, "Prepare", (PyObject *)&libevwrapper_PrepareType) == -1) INITERROR; Py_INCREF(&libevwrapper_AsyncType); if (PyModule_AddObject(module, "Async", (PyObject *)&libevwrapper_AsyncType) == -1) INITERROR; Py_INCREF(&libevwrapper_TimerType); if (PyModule_AddObject(module, "Timer", (PyObject *)&libevwrapper_TimerType) == -1) INITERROR; if (!PyEval_ThreadsInitialized()) { PyEval_InitThreads(); } #if PY_MAJOR_VERSION >= 3 return module; #endif }