aboutsummaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-11-27 16:22:46 -0200
committerHugo Lima <hugo.lima@openbossa.org>2009-11-27 16:53:13 -0200
commiteb5cadcdddf834d5df0b36d19d9411e4cf931cce (patch)
tree3ba054a53b9bde5b843748da179784fa4581d459 /libshiboken
parent3c2e7df28e219a1628f7ed0f1e63b831d07fc69c (diff)
Implemented primitives to solve the parent/children problem.
Reviewed by Marcelo Lira <marcelo.lira@openbossa.org>
Diffstat (limited to 'libshiboken')
-rw-r--r--libshiboken/basewrapper.cpp114
-rw-r--r--libshiboken/basewrapper.h51
2 files changed, 135 insertions, 30 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index bf33a9e52..7c0497f16 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -33,42 +33,109 @@
*/
#include "basewrapper.h"
+#include <cstddef>
+#include <algorithm>
namespace Shiboken
{
-PyObject*
-PyBaseWrapper_New(PyTypeObject* instanceType,
- ShiboTypeObject* baseWrapperType,
- const void* cptr,
- unsigned int hasOwnership,
- unsigned int containsCppWrapper)
+void removeParent(PyBaseWrapper* child)
+{
+ if (child->parentInfo->parent) {
+ ShiboChildrenList& oldBrothers = child->parentInfo->parent->parentInfo->children;
+ oldBrothers.remove(child);
+ child->parentInfo->parent = 0;
+ Py_DECREF(child);
+ }
+}
+
+void setParent(PyObject* parent, PyObject* child)
+{
+ if (!child || child == Py_None || child == parent)
+ return;
+
+ bool parentIsNull = !parent || parent == Py_None;
+
+ PyBaseWrapper* parent_ = reinterpret_cast<PyBaseWrapper*>(parent);
+ PyBaseWrapper* child_ = reinterpret_cast<PyBaseWrapper*>(child);
+ if (!child_->parentInfo)
+ child_->parentInfo = new ShiboParentInfo;
+
+ if (!parentIsNull) {
+ if (!parent_->parentInfo)
+ parent_->parentInfo = new ShiboParentInfo;
+ // do not re-add a child
+ ShiboChildrenList& children = parent_->parentInfo->children;
+ if (std::find(children.begin(), children.end(), child_) != children.end())
+ return;
+ }
+
+ bool hasAnotherParent = child_->parentInfo->parent && child_->parentInfo->parent != parent_;
+
+ // check if we need to remove this child from the old parent
+ if (parentIsNull || hasAnotherParent)
+ removeParent(child_);
+
+ // Add the child to the new parent
+ if (!parentIsNull) {
+ child_->parentInfo->parent = parent_;
+ parent_->parentInfo->children.push_back(child_);
+ Py_INCREF(child_);
+ }
+}
+
+void destroyParentInfo(PyBaseWrapper* obj, bool removeFromParent)
+{
+ if (removeFromParent && obj->parentInfo->parent)
+ removeParent(obj);
+ // invalidate all children
+ ShiboChildrenList::iterator it = obj->parentInfo->children.begin();
+ for (; it != obj->parentInfo->children.end(); ++it) {
+ PyBaseWrapper*& child = *it;
+ destroyParentInfo(child, false);
+ BindingManager::instance().invalidateWrapper(reinterpret_cast<PyObject*>(child));
+ Py_DECREF(child);
+ }
+ delete obj->parentInfo;
+ obj->parentInfo = 0;
+}
+
+PyObject* PyBaseWrapper_New(PyTypeObject* instanceType,
+ ShiboTypeObject* baseWrapperType,
+ const void* cptr,
+ unsigned int hasOwnership,
+ unsigned int containsCppWrapper)
{
if (!cptr)
return 0;
- PyObject* self = ((ShiboTypeObject*) instanceType)->pytype.tp_alloc((PyTypeObject*) instanceType, 0);
- ((PyBaseWrapper*)self)->baseWrapperType = baseWrapperType;
- ((PyBaseWrapper*)self)->cptr = const_cast<void*>(cptr);
- ((PyBaseWrapper*)self)->hasOwnership = hasOwnership;
- ((PyBaseWrapper*)self)->containsCppWrapper = containsCppWrapper;
- ((PyBaseWrapper*)self)->validCppObject = 1;
- if (((ShiboTypeObject*) instanceType)->mi_init && !((ShiboTypeObject*) instanceType)->mi_offsets)
- ((ShiboTypeObject*) instanceType)->mi_offsets = ((ShiboTypeObject*) instanceType)->mi_init(cptr);
- BindingManager::instance().assignWrapper(self, cptr);
- if (((ShiboTypeObject*) instanceType)->mi_offsets) {
- int* offset = ((ShiboTypeObject*) instanceType)->mi_offsets;
+ ShiboTypeObject* const& instanceType_ = reinterpret_cast<ShiboTypeObject*>(instanceType);
+ PyBaseWrapper* self = (PyBaseWrapper*)instanceType_->pytype.tp_alloc((PyTypeObject*) instanceType, 0);
+
+ self->baseWrapperType = baseWrapperType;
+ self->cptr = const_cast<void*>(cptr);
+ self->hasOwnership = hasOwnership;
+ self->containsCppWrapper = containsCppWrapper;
+ self->validCppObject = 1;
+ self->parentInfo = 0;
+
+ if (instanceType_->mi_init && !instanceType_->mi_offsets)
+ instanceType_->mi_offsets = instanceType_->mi_init(cptr);
+ BindingManager::instance().assignWrapper(reinterpret_cast<PyObject*>(self), cptr);
+ if (instanceType_->mi_offsets) {
+ int* offset = instanceType_->mi_offsets;
while (*offset != -1) {
- if (*offset > 0)
- BindingManager::instance().assignWrapper(self, (void*) ((size_t) cptr + (*offset)));
+ if (*offset > 0) {
+ BindingManager::instance().assignWrapper(reinterpret_cast<PyObject*>(self),
+ reinterpret_cast<void*>((std::size_t) cptr + (*offset)));
+ }
offset++;
}
}
- return self;
+ return reinterpret_cast<PyObject*>(self);
}
-bool
-cppObjectIsInvalid(PyObject* wrapper)
+bool cppObjectIsInvalid(PyObject* wrapper)
{
if (((Shiboken::PyBaseWrapper*)wrapper)->validCppObject)
return false;
@@ -76,8 +143,7 @@ cppObjectIsInvalid(PyObject* wrapper)
return true;
}
-void
-PyBaseWrapper_Dealloc_PrivateDtor(PyObject* self)
+void PyBaseWrapper_Dealloc_PrivateDtor(PyObject* self)
{
BindingManager::instance().releaseWrapper(self);
Py_TYPE(((PyBaseWrapper*)self))->tp_free((PyObject*)self);
diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h
index a65c9096a..90c38c735 100644
--- a/libshiboken/basewrapper.h
+++ b/libshiboken/basewrapper.h
@@ -37,18 +37,34 @@
#include <Python.h>
#include "bindingmanager.h"
+#include <list>
namespace Shiboken
{
-extern "C"
+struct PyBaseWrapper;
+
+/// Linked list of PyBaseWrapper pointers
+typedef std::list<PyBaseWrapper*> ShiboChildrenList;
+
+/// Struct used to store information about object parent and children.
+struct LIBSHIBOKEN_API ShiboParentInfo
{
+ /// Default ctor.
+ ShiboParentInfo() : parent(0) {}
+ /// Pointer to parent object.
+ PyBaseWrapper* parent;
+ /// List of object children.
+ ShiboChildrenList children;
+};
+extern "C"
+{
/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance.
typedef int* (*MultipleInheritanceInitFunction)(const void*);
-// PyTypeObject extended with C++ multiple inheritance information.
-struct ShiboTypeObject
+/// PyTypeObject extended with C++ multiple inheritance information.
+struct LIBSHIBOKEN_API ShiboTypeObject
{
PyTypeObject pytype;
int* mi_offsets;
@@ -56,7 +72,7 @@ struct ShiboTypeObject
};
/// Base Python object for all the wrapped C++ classes.
-struct PyBaseWrapper
+struct LIBSHIBOKEN_API PyBaseWrapper
{
PyObject_HEAD
/// First binding provided parent type of a Python class that inherits from a wrapped class.
@@ -69,10 +85,32 @@ struct PyBaseWrapper
unsigned int containsCppWrapper : 1;
/// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not.
unsigned int validCppObject : 1;
+ /// Information about the object parents and children, can be null.
+ ShiboParentInfo* parentInfo;
};
} // extern "C"
+/**
+* Set the parent of \p child to \p parent.
+* When an object dies, all their children, granchildren, etc, are tagged as invalid.
+* \param parent the parent object, if null, the child will have no parents.
+* \param child the child.
+*/
+LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child);
+
+/**
+* Remove this child from their parent, if any.
+* \param child the child.
+*/
+LIBSHIBOKEN_API void removeParent(PyBaseWrapper* child);
+
+/**
+* \internal This is an internal function called by PyBaseWrapper_Dealloc, it's exported just for techinical reasons.
+* \note Do not call this function inside your bindings.
+*/
+LIBSHIBOKEN_API void destroyParentInfo(PyBaseWrapper* obj, bool removeFromParent = true);
+
#define PyBaseWrapper_Check(op) PyObject_TypeCheck(op, &Shiboken::PyBaseWrapper_Type)
#define PyBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::PyBaseWrapper_Type)
@@ -80,6 +118,7 @@ struct PyBaseWrapper
#define PyBaseWrapper_setCptr(pyobj,c) (((Shiboken::PyBaseWrapper*)pyobj)->cptr = c)
#define PyBaseWrapper_hasOwnership(pyobj) (((Shiboken::PyBaseWrapper*)pyobj)->hasOwnership)
#define PyBaseWrapper_setOwnership(pyobj,o) (((Shiboken::PyBaseWrapper*)pyobj)->hasOwnership = o)
+#define PyBaseWrapper_hasParentInfo(pyobj) (((Shiboken::PyBaseWrapper*)pyobj)->parentInfo)
#define PyBaseWrapper_containsCppWrapper(pyobj) (((Shiboken::PyBaseWrapper*)pyobj)->containsCppWrapper)
#define PyBaseWrapper_setContainsCppWrapper(pyobj,o)(((Shiboken::PyBaseWrapper*)pyobj)->containsCppWrapper= o)
#define PyBaseWrapper_validCppObject(pyobj) (((Shiboken::PyBaseWrapper*)pyobj)->validCppObject)
@@ -133,7 +172,6 @@ typedef struct {
#define Py_TPFLAGS_HAVE_NEWBUFFER 0
#endif
-
LIBSHIBOKEN_API PyAPI_FUNC(PyObject*)
PyBaseWrapper_New(PyTypeObject* instanceType,
ShiboTypeObject* baseWrapperType,
@@ -150,6 +188,8 @@ void PyBaseWrapper_Dealloc(PyObject* self)
BindingManager::instance().releaseWrapper(self);
if (PyBaseWrapper_hasOwnership(self))
delete ((T*)PyBaseWrapper_cptr(self));
+ if (PyBaseWrapper_hasParentInfo(self))
+ destroyParentInfo(reinterpret_cast<PyBaseWrapper*>(self));
Py_TYPE(((PyBaseWrapper*)self))->tp_free((PyObject*)self);
}
@@ -158,4 +198,3 @@ LIBSHIBOKEN_API PyAPI_FUNC(void) PyBaseWrapper_Dealloc_PrivateDtor(PyObject* sel
} // namespace Shiboken
#endif // BASEWRAPPER_H
-