diff options
Diffstat (limited to 'libs/python/src/object/life_support.cpp')
-rw-r--r-- | libs/python/src/object/life_support.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/libs/python/src/object/life_support.cpp b/libs/python/src/object/life_support.cpp new file mode 100644 index 000000000..b7e9aa861 --- /dev/null +++ b/libs/python/src/object/life_support.cpp @@ -0,0 +1,121 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#include <boost/python/object/life_support.hpp> +#include <boost/python/detail/none.hpp> +#include <boost/python/refcount.hpp> + +namespace boost { namespace python { namespace objects { + +struct life_support +{ + PyObject_HEAD + PyObject* patient; +}; + +extern "C" +{ + static void + life_support_dealloc(PyObject* self) + { + Py_XDECREF(((life_support*)self)->patient); + self->ob_type->tp_free(self); + } + + static PyObject * + life_support_call(PyObject *self, PyObject *arg, PyObject * /*kw*/) + { + // Let the patient die now + Py_XDECREF(((life_support*)self)->patient); + ((life_support*)self)->patient = 0; + // Let the weak reference die. This probably kills us. + Py_XDECREF(PyTuple_GET_ITEM(arg, 0)); + return ::boost::python::detail::none(); + } +} + +PyTypeObject life_support_type = { + PyVarObject_HEAD_INIT(NULL, 0)//(&PyType_Type) + const_cast<char*>("Boost.Python.life_support"), + sizeof(life_support), + 0, + life_support_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, //(reprfunc)func_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + life_support_call, /* tp_call */ + 0, /* tp_str */ + 0, // PyObject_GenericGetAttr, /* tp_getattro */ + 0, // PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ + 0, /* tp_doc */ + 0, // (traverseproc)func_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, // func_memberlist, /* tp_members */ + 0, //func_getsetlist, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ +#if PYTHON_API_VERSION >= 1012 + 0 /* tp_del */ +#endif +}; + +PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) +{ + if (nurse == Py_None || nurse == patient) + return nurse; + + if (Py_TYPE(&life_support_type) == 0) + { + Py_TYPE(&life_support_type) = &PyType_Type; + PyType_Ready(&life_support_type); + } + + life_support* system = PyObject_New(life_support, &life_support_type); + if (!system) + return 0; + + system->patient = 0; + + // We're going to leak this reference, but don't worry; the + // life_support system decrements it when the nurse dies. + PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system); + + // weakref has either taken ownership, or we have to release it + // anyway + Py_DECREF(system); + if (!weakref) + return 0; + + system->patient = patient; + Py_XINCREF(patient); // hang on to the patient until death + return weakref; +} + +}}} // namespace boost::python::objects |