kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit 47776a9fbbb49a64525a626c15569acab41dcc44
parent c41c1db303786f56f407ec87c550ab3c002498b7
Author: Joris Vink <joris@coders.se>
Date:   Tue, 23 Oct 2018 20:44:43 +0200

Hook kore timers into python.

Diffstat:
include/kore/kore.h | 1+
include/kore/python_methods.h | 28++++++++++++++++++++++++++++
src/python.c | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/include/kore/kore.h b/include/kore/kore.h @@ -193,6 +193,7 @@ TAILQ_HEAD(netbuf_head, netbuf); #define WEBSOCKET_BROADCAST_GLOBAL 2 #define KORE_TIMER_ONESHOT 0x01 +#define KORE_TIMER_FLAGS (KORE_TIMER_ONESHOT) #define KORE_CONNECTION_PRUNE_DISCONNECT 0 #define KORE_CONNECTION_PRUNE_ALL 1 diff --git a/include/kore/python_methods.h b/include/kore/python_methods.h @@ -30,6 +30,7 @@ struct python_coro { static PyObject *python_kore_log(PyObject *, PyObject *); static PyObject *python_kore_lock(PyObject *, PyObject *); static PyObject *python_kore_bind(PyObject *, PyObject *); +static PyObject *python_kore_timer(PyObject *, PyObject *); static PyObject *python_kore_fatal(PyObject *, PyObject *); static PyObject *python_kore_queue(PyObject *, PyObject *); static PyObject *python_kore_fatalx(PyObject *, PyObject *); @@ -53,6 +54,7 @@ static struct PyMethodDef pykore_methods[] = { METHOD("log", python_kore_log, METH_VARARGS), METHOD("lock", python_kore_lock, METH_NOARGS), METHOD("bind", python_kore_bind, METH_VARARGS), + METHOD("timer", python_kore_timer, METH_VARARGS), METHOD("queue", python_kore_queue, METH_VARARGS), METHOD("fatal", python_kore_fatal, METH_VARARGS), METHOD("fatalx", python_kore_fatalx, METH_VARARGS), @@ -71,6 +73,32 @@ static struct PyModuleDef pykore_module = { PyModuleDef_HEAD_INIT, "kore", NULL, -1, pykore_methods }; +struct pytimer { + PyObject_HEAD + int flags; + struct kore_timer *run; + PyObject *callable; +}; + +static PyObject *pytimer_close(struct pytimer *, PyObject *); + +static PyMethodDef pytimer_methods[] = { + METHOD("close", pytimer_close, METH_NOARGS), + METHOD(NULL, NULL, -1) +}; + +static void pytimer_dealloc(struct pytimer *); + +static PyTypeObject pytimer_type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "kore.timer", + .tp_doc = "kore timer implementation", + .tp_methods = pytimer_methods, + .tp_basicsize = sizeof(struct pytimer), + .tp_dealloc = (destructor)pytimer_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + struct pysocket { PyObject_HEAD int fd; diff --git a/src/python.c b/src/python.c @@ -53,6 +53,7 @@ static PyObject *pysocket_async_accept(struct pysocket_op *); static PyObject *pysocket_async_connect(struct pysocket_op *); static void pylock_do_release(struct pylock *); +static void pytimer_run(void *, u_int64_t); #if defined(KORE_USE_PGSQL) static PyObject *pykore_pgsql_alloc(struct http_request *, @@ -100,7 +101,7 @@ struct kore_runtime kore_python_runtime = { .onload = python_runtime_onload, .connect = python_runtime_connect, .execute = python_runtime_execute, - .configure = python_runtime_configure + .configure = python_runtime_configure, }; static struct { @@ -115,6 +116,7 @@ static struct { { "RESULT_ERROR", KORE_RESULT_ERROR }, { "MODULE_LOAD", KORE_MODULE_LOAD }, { "MODULE_UNLOAD", KORE_MODULE_UNLOAD }, + { "TIMER_ONESHOT", KORE_TIMER_ONESHOT }, { "CONN_PROTO_HTTP", CONN_PROTO_HTTP }, { "CONN_PROTO_UNKNOWN", CONN_PROTO_UNKNOWN }, { "CONN_PROTO_WEBSOCKET", CONN_PROTO_WEBSOCKET }, @@ -718,6 +720,7 @@ python_module_init(void) fatal("python_module_init: failed to setup pykore module"); python_push_type("pylock", pykore, &pylock_type); + python_push_type("pytimer", pykore, &pytimer_type); python_push_type("pyqueue", pykore, &pyqueue_type); python_push_type("pysocket", pykore, &pysocket_type); python_push_type("pysocket_op", pykore, &pysocket_op_type); @@ -967,6 +970,37 @@ python_kore_shutdown(PyObject *self, PyObject *args) } static PyObject * +python_kore_timer(PyObject *self, PyObject *args) +{ + u_int64_t ms; + PyObject *obj; + int flags; + struct pytimer *timer; + + if (!PyArg_ParseTuple(args, "OKi", &obj, &ms, &flags)) + return (NULL); + + if (flags & ~(KORE_TIMER_FLAGS)) { + PyErr_SetString(PyExc_RuntimeError, "invalid flags"); + return (NULL); + } + + if ((timer = PyObject_New(struct pytimer, &pytimer_type)) == NULL) + return (NULL); + + timer->flags = flags; + timer->callable = obj; + timer->run = kore_timer_add(pytimer_run, ms, timer, flags); + + printf("timer of %llu ms started (0x%04x)\n", ms, flags); + + Py_INCREF((PyObject *)timer); + Py_INCREF(timer->callable); + + return ((PyObject *)timer); +} + +static PyObject * python_import(const char *path) { PyObject *module; @@ -1072,6 +1106,56 @@ pyconnection_get_addr(struct pyconnection *pyc, void *closure) } static void +pytimer_run(void *arg, u_int64_t now) +{ + PyObject *ret; + struct pytimer *timer = arg; + + PyErr_Clear(); + ret = PyObject_CallObject(timer->callable, NULL); + Py_DECREF(ret); + + if (timer->flags & KORE_TIMER_ONESHOT) { + timer->run = NULL; + Py_DECREF((PyObject *)timer); + } +} + +static void +pytimer_dealloc(struct pytimer *timer) +{ + if (timer->run != NULL) { + kore_timer_remove(timer->run); + timer->run = NULL; + } + + if (timer->callable != NULL) { + Py_DECREF(timer->callable); + timer->callable = NULL; + } + + PyObject_Del((PyObject *)timer); +} + +static PyObject * +pytimer_close(struct pytimer *timer, PyObject *args) +{ + if (timer->run != NULL) { + kore_timer_remove(timer->run); + timer->run = NULL; + } + + if (timer->callable != NULL) { + Py_DECREF(timer->callable); + timer->callable = NULL; + } + + Py_DECREF((PyObject *)timer); + + Py_RETURN_TRUE; +} + +static void pysocket_dealloc(struct pysocket *sock) { PyObject_Del((PyObject *)sock);