aboutsummaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2010-02-12 01:28:01 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2010-02-12 15:24:39 -0300
commit2c07ee6229c012ee3624fcdf0fbb281bfef964d7 (patch)
tree11a479876e02af47f3819a8e2f6cc676c58daf85 /libshiboken
parent40f7ab459308a71d5fdabd82de758f7fac01c63b (diff)
Adds support for managing objects referred by a Python wrapper.
A mapping to referred objects has been added to the SbkBaseWrapper structure to keep track of objects used by a given Python wrapper. This differs from ownership or parenting, since the referee is not responsible for destroying the referred object. It is more akin to a model/view relationship when many views refers to one model but don't own it, and the model must be kept alive as long it is referred. Two methods were added to assist the reference keeping: * SbkBaseWrapper_keepReference Causes a referred object reference counter to be increased and any previous used object refcount is decreased. SbkBaseWrapper_clearReferences Decrements the reference counter of all referred objects. It is called when the Python wrapper referee is destroyed.
Diffstat (limited to 'libshiboken')
-rw-r--r--libshiboken/basewrapper.cpp24
-rw-r--r--libshiboken/basewrapper.h33
2 files changed, 56 insertions, 1 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index c23e677df..79ee3cfcf 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -150,6 +150,7 @@ PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*)
self->parentInfo = 0;
self->ob_dict = 0;
self->weakreflist = 0;
+ self->referredObjects = 0;
return reinterpret_cast<PyObject*>(self);
}
@@ -171,6 +172,29 @@ void SbkBaseWrapper_Dealloc_PrivateDtor(PyObject* self)
Py_TYPE(reinterpret_cast<SbkBaseWrapper*>(self))->tp_free(self);
}
+void SbkBaseWrapper_keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject)
+{
+ if (!self->referredObjects)
+ return;
+ RefCountMap& refCountMap = *(self->referredObjects);
+ Py_INCREF(referredObject);
+ RefCountMap::iterator iter = refCountMap.find(key);
+ if (iter != refCountMap.end())
+ Py_DECREF(iter->second);
+ refCountMap[key] = referredObject;
+}
+
+void SbkBaseWrapper_clearReferences(SbkBaseWrapper* self)
+{
+ if (!self->referredObjects)
+ return;
+ RefCountMap& refCountMap = *(self->referredObjects);
+ RefCountMap::iterator iter;
+ for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter)
+ Py_DECREF(iter->second);
+ delete self->referredObjects;
+}
+
// Wrapper metatype and base type ----------------------------------------------------------
extern "C"
diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h
index bc020d2a2..7d834da0e 100644
--- a/libshiboken/basewrapper.h
+++ b/libshiboken/basewrapper.h
@@ -38,6 +38,7 @@
#include <Python.h>
#include "bindingmanager.h"
#include <list>
+#include <map>
namespace Shiboken
{
@@ -58,6 +59,12 @@ struct LIBSHIBOKEN_API ShiboParentInfo
ShiboChildrenList children;
};
+/**
+ * This mapping associates a method and argument of an wrapper object with the wrapper of
+ * said argument when it needs the binding to help manage its reference counting.
+ */
+typedef std::map<const char*, PyObject*> RefCountMap;
+
extern "C"
{
/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance.
@@ -102,7 +109,9 @@ struct LIBSHIBOKEN_API SbkBaseWrapper
/// Information about the object parents and children, can be null.
ShiboParentInfo* parentInfo;
/// List of weak references
- PyObject *weakreflist;
+ PyObject* weakreflist;
+ /// Manage reference counting of objects that are referred but not owned.
+ RefCountMap* referredObjects;
};
LIBSHIBOKEN_API PyAPI_FUNC(void) init_shiboken();
@@ -206,6 +215,27 @@ SbkBaseWrapper_New(SbkBaseWrapperType* instanceType,
LIBSHIBOKEN_API PyAPI_FUNC(PyObject*)
SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*);
+
+/**
+ * Increments the reference count of the referred Python object.
+ * A previous Python object in the same position identified by the 'key' parameter
+ * will have its reference counter decremented automatically when replaced.
+ * All the kept references should be decremented when the Python wrapper indicated by
+ * 'self' dies.
+ * No checking is done for any of the passed arguments, since it is meant to be used
+ * by generated code it is supposed that the generator is correct.
+ * \param self the wrapper instance that keeps references to other objects.
+ * \param key a key that identifies the C++ method signature and argument where the referredObject came from.
+ * \parem referredObject the object whose reference is used by the self object.
+ */
+LIBSHIBOKEN_API void SbkBaseWrapper_keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject);
+
+/**
+ * Decrements the reference counters of every object referred by self.
+ * \param self the wrapper instance that keeps references to other objects.
+ */
+LIBSHIBOKEN_API void SbkBaseWrapper_clearReferences(SbkBaseWrapper* self);
+
/// Returns true and sets a Python RuntimeError if the Python wrapper is not marked as valid.
LIBSHIBOKEN_API bool cppObjectIsInvalid(PyObject* wrapper);
@@ -220,6 +250,7 @@ void SbkBaseWrapper_Dealloc(PyObject* self)
delete (reinterpret_cast<T*>(SbkBaseWrapper_cptr(self)));
if (SbkBaseWrapper_hasParentInfo(self))
destroyParentInfo(reinterpret_cast<SbkBaseWrapper*>(self));
+ SbkBaseWrapper_clearReferences(reinterpret_cast<SbkBaseWrapper*>(self));
Py_TYPE(reinterpret_cast<SbkBaseWrapper*>(self))->tp_free(self);
}