122 lines
4.6 KiB
C++
122 lines
4.6 KiB
C++
// 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
|