• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
life_support_dealloc(PyObject * self)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 *
life_support_call(PyObject * self,PyObject * arg,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 
make_nurse_and_patient(PyObject * nurse,PyObject * patient)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     {
96         Py_TYPE(&life_support_type) = &PyType_Type;
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
122