--- /dev/null
+/* These two macros are basicly Py_BEGIN_ALLOW_THREADS and Py_BEGIN_ALLOW_THREADS
+ * from the other direction. If a Python thread calls a C function
+ * Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
+ * we don't intend to call any Python functions.
+ *
+ * These two macros are used whenever a C thread intends to call some Python
+ * function, usually because some registered callback was triggered.
+ * Just like Py_BEGIN_ALLOW_THREADS it opens a block so these macros have to be
+ * used in pairs. They aquire the GIL, create a new Python thread state and swap
+ * the current thread state with the new one. This means this thread is now allowed
+ * to execute Python code. */
+
+#define CPY_LOCK_THREADS {\
+ PyGILState_STATE gil_state;\
+ gil_state = PyGILState_Ensure();
+
+#define CPY_RELEASE_THREADS \
+ PyGILState_Release(gil_state);\
+}
+
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_VISIT
+#define Py_VISIT(o) do {\
+ int _vret;\
+ if ((o) != NULL) {\
+ _vret = visit((o), arg);\
+ if (_vret != 0)\
+ return _vret;\
+ }\
+} while (0)
+#endif
+
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_CLEAR
+#define Py_CLEAR(o) do {\
+ PyObject *tmp = o;\
+ (o) = NULL;\
+ Py_XDECREF(tmp);\
+} while (0)
+#endif
+
+typedef struct {
+ PyObject_HEAD /* No semicolon! */
+ PyObject *parent;
+ PyObject *key;
+ PyObject *values;
+ PyObject *children;
+} Config;
+
+PyTypeObject ConfigType;
--- /dev/null
+#include <Python.h>
+#include <structmember.h>
+
+#include "collectd.h"
+#include "common.h"
+
+#include "cpython.h"
+
+static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ Config *self;
+
+ self = (Config *) type->tp_alloc(type, 0);
+ if (self == NULL)
+ return NULL;
+
+ self->parent = NULL;
+ self->key = NULL;
+ self->values = NULL;
+ self->children = NULL;
+ return (PyObject *) self;
+}
+
+static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) {
+ PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
+ Config *self = (Config *) s;
+ static char *kwlist[] = {"key", "parent", "values", "children", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|OOO", kwlist,
+ &key, &parent, &values, &children))
+ return -1;
+
+ if (values == NULL) {
+ values = PyTuple_New(0);
+ PyErr_Clear();
+ }
+ if (children == NULL) {
+ children = PyTuple_New(0);
+ PyErr_Clear();
+ }
+ tmp = self->key;
+ Py_INCREF(key);
+ self->key = key;
+ Py_XDECREF(tmp);
+ if (parent != NULL) {
+ tmp = self->parent;
+ Py_INCREF(parent);
+ self->parent = parent;
+ Py_XDECREF(tmp);
+ }
+ if (values != NULL) {
+ tmp = self->values;
+ Py_INCREF(values);
+ self->values = values;
+ Py_XDECREF(tmp);
+ }
+ if (children != NULL) {
+ tmp = self->children;
+ Py_INCREF(children);
+ self->children = children;
+ Py_XDECREF(tmp);
+ }
+ return 0;
+}
+
+static PyObject *Config_repr(PyObject *s) {
+ Config *self = (Config *) s;
+
+ return PyString_FromFormat("<collectd.Config %snode %s>", self->parent == Py_None ? "root " : "", PyString_AsString(PyObject_Str(self->key)));
+}
+
+static int Config_traverse(PyObject *self, visitproc visit, void *arg) {
+ Config *c = (Config *) self;
+ Py_VISIT(c->parent);
+ Py_VISIT(c->key);
+ Py_VISIT(c->values);
+ Py_VISIT(c->children);
+ return 0;
+}
+
+static int Config_clear(PyObject *self) {
+ Config *c = (Config *) self;
+ Py_CLEAR(c->parent);
+ Py_CLEAR(c->key);
+ Py_CLEAR(c->values);
+ Py_CLEAR(c->children);
+ return 0;
+}
+
+static void Config_dealloc(PyObject *self) {
+ Config_clear(self);
+ self->ob_type->tp_free(self);
+}
+
+static PyMemberDef Config_members[] = {
+ {"Parent", T_OBJECT, offsetof(Config, parent), 0, "Parent node"},
+ {"Key", T_OBJECT_EX, offsetof(Config, key), 0, "Keyword of this node"},
+ {"Values", T_OBJECT_EX, offsetof(Config, values), 0, "Values after the key"},
+ {"Children", T_OBJECT_EX, offsetof(Config, children), 0, "Childnodes of this node"},
+ {NULL}
+};
+
+PyTypeObject ConfigType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* Always 0 */
+ "collectd.Config", /* tp_name */
+ sizeof(Config), /* tp_basicsize */
+ 0, /* Will be filled in later */
+ Config_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ Config_repr, /* 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 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+ "Cool help text later", /* tp_doc */
+ Config_traverse, /* tp_traverse */
+ Config_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ Config_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ Config_init, /* tp_init */
+ 0, /* tp_alloc */
+ Config_new /* tp_new */
+};
+
#include "collectd.h"
#include "common.h"
+#include "cpython.h"
+
typedef struct cpy_callback_s {
char *name;
PyObject *callback;
static PyThreadState *state;
-/* Serves the same purpose as PyEval_ThreadsInitialized but doesn't require
- * Python 2.4. */
-
-static int cpy_have_threads;
-
-/* These two macros are basicly Py_BEGIN_ALLOW_THREADS and Py_BEGIN_ALLOW_THREADS
- * from the other direction. If a Python thread calls a C function
- * Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
- * we don't intend to call any Python functions.
- *
- * These two macros are used whenever a C thread intends to call some Python
- * function, usually because some registered callback was triggered.
- * Just like Py_BEGIN_ALLOW_THREADS it opens a block so these macros have to be
- * used in pairs. They aquire the GIL, create a new Python thread state and swap
- * the current thread state with the new one. This means this thread is now allowed
- * to execute Python code. */
-
-#define CPY_LOCK_THREADS {\
- PyGILState_STATE gil_state;\
- if (cpy_have_threads)\
- gil_state = PyGILState_Ensure();
-
-#define CPY_RELEASE_THREADS \
- if (cpy_have_threads)\
- PyGILState_Release(gil_state);\
-}
-
-
static cpy_callback_t *cpy_config_callbacks;
static cpy_callback_t *cpy_init_callbacks;
static cpy_callback_t *cpy_shutdown_callbacks;
CPY_RELEASE_THREADS
}
-typedef struct {
- PyObject_HEAD /* No semicolon! */
- PyObject *parent;
- PyObject *key;
- PyObject *values;
- PyObject *children;
-} Config;
-
-static void Config_dealloc(PyObject *s) {
- Config *self = (Config *) s;
-
- Py_XDECREF(self->parent);
- Py_XDECREF(self->key);
- Py_XDECREF(self->values);
- Py_XDECREF(self->children);
- self->ob_type->tp_free(s);
-}
-
-static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
- Config *self;
-
- self = (Config *) type->tp_alloc(type, 0);
- if (self == NULL)
- return NULL;
-
- self->parent = NULL;
- self->key = NULL;
- self->values = NULL;
- self->children = NULL;
- return (PyObject *) self;
-}
-
-static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) {
- PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
- Config *self = (Config *) s;
- static char *kwlist[] = {"key", "parent", "values", "children", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|OOO", kwlist,
- &key, &parent, &values, &children))
- return -1;
-
- if (values == NULL) {
- values = PyTuple_New(0);
- PyErr_Clear();
- }
- if (children == NULL) {
- children = PyTuple_New(0);
- PyErr_Clear();
- }
- tmp = self->key;
- Py_INCREF(key);
- self->key = key;
- Py_XDECREF(tmp);
- if (parent != NULL) {
- tmp = self->parent;
- Py_INCREF(parent);
- self->parent = parent;
- Py_XDECREF(tmp);
- }
- if (values != NULL) {
- tmp = self->values;
- Py_INCREF(values);
- self->values = values;
- Py_XDECREF(tmp);
- }
- if (children != NULL) {
- tmp = self->children;
- Py_INCREF(children);
- self->children = children;
- Py_XDECREF(tmp);
- }
- return 0;
-}
-
-static PyMemberDef Config_members[] = {
- {"Parent", T_OBJECT, offsetof(Config, parent), 0, "Parent node"},
- {"Key", T_OBJECT_EX, offsetof(Config, key), 0, "Keyword of this node"},
- {"Values", T_OBJECT_EX, offsetof(Config, values), 0, "Values after the key"},
- {"Children", T_OBJECT_EX, offsetof(Config, children), 0, "Childnodes of this node"},
- {NULL}
-};
-
-static PyTypeObject ConfigType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* Always 0 */
- "collectd.Config", /* tp_name */
- sizeof(Config), /* tp_basicsize */
- 0, /* Will be filled in later */
- Config_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*/
- "Cool help text later", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- Config_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- Config_init, /* tp_init */
- 0, /* tp_alloc */
- Config_new /* tp_new */
-};
-
static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
cpy_callback_t *c;
const char *name = NULL;
PyObject *ret;
PyEval_InitThreads();
- cpy_have_threads = 1;
/* Now it's finally OK to use python threads. */
for (c = cpy_init_callbacks; c; c = c->next) {
if (c->data == NULL)