diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-02-12 01:28:01 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-02-12 15:24:39 -0300 |
commit | 2c07ee6229c012ee3624fcdf0fbb281bfef964d7 (patch) | |
tree | 11a479876e02af47f3819a8e2f6cc676c58daf85 /libshiboken | |
parent | 40f7ab459308a71d5fdabd82de758f7fac01c63b (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.cpp | 24 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 33 |
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); } |