]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright David Abrahams 2002. |
2 | // Distributed under the Boost Software License, Version 1.0. (See | |
3 | // accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | #include <boost/python/object/life_support.hpp> | |
6 | #include <boost/python/detail/none.hpp> | |
7 | #include <boost/python/refcount.hpp> | |
8 | ||
9 | namespace boost { namespace python { namespace objects { | |
10 | ||
11 | struct life_support | |
12 | { | |
13 | PyObject_HEAD | |
14 | PyObject* patient; | |
15 | }; | |
16 | ||
17 | extern "C" | |
18 | { | |
19 | static void | |
20 | life_support_dealloc(PyObject* self) | |
21 | { | |
22 | Py_XDECREF(((life_support*)self)->patient); | |
23 | self->ob_type->tp_free(self); | |
24 | } | |
25 | ||
26 | static PyObject * | |
27 | life_support_call(PyObject *self, PyObject *arg, PyObject * /*kw*/) | |
28 | { | |
29 | // Let the patient die now | |
30 | Py_XDECREF(((life_support*)self)->patient); | |
31 | ((life_support*)self)->patient = 0; | |
32 | // Let the weak reference die. This probably kills us. | |
33 | Py_XDECREF(PyTuple_GET_ITEM(arg, 0)); | |
34 | return ::boost::python::detail::none(); | |
35 | } | |
36 | } | |
37 | ||
38 | PyTypeObject life_support_type = { | |
39 | PyVarObject_HEAD_INIT(NULL, 0)//(&PyType_Type) | |
40 | const_cast<char*>("Boost.Python.life_support"), | |
41 | sizeof(life_support), | |
42 | 0, | |
43 | life_support_dealloc, /* tp_dealloc */ | |
44 | 0, /* tp_print */ | |
45 | 0, /* tp_getattr */ | |
46 | 0, /* tp_setattr */ | |
47 | 0, /* tp_compare */ | |
48 | 0, //(reprfunc)func_repr, /* tp_repr */ | |
49 | 0, /* tp_as_number */ | |
50 | 0, /* tp_as_sequence */ | |
51 | 0, /* tp_as_mapping */ | |
52 | 0, /* tp_hash */ | |
53 | life_support_call, /* tp_call */ | |
54 | 0, /* tp_str */ | |
55 | 0, // PyObject_GenericGetAttr, /* tp_getattro */ | |
56 | 0, // PyObject_GenericSetAttr, /* tp_setattro */ | |
57 | 0, /* tp_as_buffer */ | |
58 | Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ | |
59 | 0, /* tp_doc */ | |
60 | 0, // (traverseproc)func_traverse, /* tp_traverse */ | |
61 | 0, /* tp_clear */ | |
62 | 0, /* tp_richcompare */ | |
63 | 0, //offsetof(PyLife_SupportObject, func_weakreflist), /* tp_weaklistoffset */ | |
64 | 0, /* tp_iter */ | |
65 | 0, /* tp_iternext */ | |
66 | 0, /* tp_methods */ | |
67 | 0, // func_memberlist, /* tp_members */ | |
68 | 0, //func_getsetlist, /* tp_getset */ | |
69 | 0, /* tp_base */ | |
70 | 0, /* tp_dict */ | |
71 | 0, /* tp_descr_get */ | |
72 | 0, /* tp_descr_set */ | |
73 | 0, //offsetof(PyLife_SupportObject, func_dict), /* tp_dictoffset */ | |
74 | 0, /* tp_init */ | |
75 | 0, /* tp_alloc */ | |
76 | 0, /* tp_new */ | |
77 | 0, /* tp_free */ | |
78 | 0, /* tp_is_gc */ | |
79 | 0, /* tp_bases */ | |
80 | 0, /* tp_mro */ | |
81 | 0, /* tp_cache */ | |
82 | 0, /* tp_subclasses */ | |
83 | 0, /* tp_weaklist */ | |
84 | #if PYTHON_API_VERSION >= 1012 | |
85 | 0 /* tp_del */ | |
86 | #endif | |
87 | }; | |
88 | ||
89 | PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) | |
90 | { | |
91 | if (nurse == Py_None || nurse == patient) | |
92 | return nurse; | |
93 | ||
94 | if (Py_TYPE(&life_support_type) == 0) | |
95 | { | |
1e59de90 | 96 | Py_SET_TYPE(&life_support_type, &PyType_Type); |
7c673cae FG |
97 | PyType_Ready(&life_support_type); |
98 | } | |
99 | ||
100 | life_support* system = PyObject_New(life_support, &life_support_type); | |
101 | if (!system) | |
102 | return 0; | |
103 | ||
104 | system->patient = 0; | |
105 | ||
106 | // We're going to leak this reference, but don't worry; the | |
107 | // life_support system decrements it when the nurse dies. | |
108 | PyObject* weakref = PyWeakref_NewRef(nurse, (PyObject*)system); | |
109 | ||
110 | // weakref has either taken ownership, or we have to release it | |
111 | // anyway | |
112 | Py_DECREF(system); | |
113 | if (!weakref) | |
114 | return 0; | |
115 | ||
116 | system->patient = patient; | |
117 | Py_XINCREF(patient); // hang on to the patient until death | |
118 | return weakref; | |
119 | } | |
120 | ||
121 | }}} // namespace boost::python::objects |