diff options
author | Renato Filho <renato.filho@openbossa.org> | 2010-07-09 15:29:30 -0300 |
---|---|---|
committer | Renato Filho <renato.filho@openbossa.org> | 2010-07-09 19:26:16 -0300 |
commit | 4807359481f136145f404421ab8e99dd5f4cfefd (patch) | |
tree | bf5c7a71223e65b771cc99f5eee328a9c189745a /libshiboken | |
parent | c740aa812e6556747c51f2ac117c7107739aacab (diff) |
Use list on keep reference map.
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'libshiboken')
-rw-r--r-- | libshiboken/basewrapper.cpp | 56 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 5 |
2 files changed, 52 insertions, 9 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 21e429535..799c21252 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -47,6 +47,9 @@ namespace Shiboken static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); +static std::list<PyObject*> splitPyObject(PyObject* pyObj); +static void incRefPyObject(PyObject* pyObj); +static void decRefPyObjectlist(const std::list<PyObject*> &pyObj); extern "C" { @@ -374,7 +377,7 @@ void deallocWrapperWithPrivateDtor(PyObject* self) Py_TYPE(reinterpret_cast<SbkBaseWrapper*>(self))->tp_free(self); } -void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject) +void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject, bool append) { bool isNone = (!referredObject || (referredObject == Py_None)); if (!self->referredObjects) @@ -382,16 +385,21 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje RefCountMap& refCountMap = *(self->referredObjects); if (!isNone) - Py_INCREF(referredObject); + incRefPyObject(referredObject); RefCountMap::iterator iter = refCountMap.find(key); - if (iter != refCountMap.end()){ - Py_DECREF(iter->second); + if (!append && (iter != refCountMap.end())) { + decRefPyObjectlist(iter->second); refCountMap.erase(iter); } - if (!isNone) - refCountMap[key] = referredObject; + if (!isNone) { + std::list<PyObject*> values = splitPyObject(referredObject); + if (append && (iter != refCountMap.end())) + refCountMap[key].assign(values.begin(), values.end()); + else + refCountMap[key] = values; + } } void clearReferences(SbkBaseWrapper* self) @@ -402,7 +410,7 @@ void clearReferences(SbkBaseWrapper* self) RefCountMap& refCountMap = *(self->referredObjects); RefCountMap::iterator iter; for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) - Py_DECREF(iter->second); + decRefPyObjectlist(iter->second); delete self->referredObjects; self->referredObjects = 0; } @@ -639,6 +647,40 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } +static std::list<PyObject*> splitPyObject(PyObject* pyObj) +{ + std::list<PyObject*> result; + if (PySequence_Check(pyObj)) { + AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); + for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { + result.push_back(PySequence_Fast_GET_ITEM(lst.object(), i)); + } + } else { + result.push_back(pyObj); + } + return result; +} + +static void incRefPyObject(PyObject* pyObj) +{ + if (PySequence_Check(pyObj)) { + for(int i = 0, i_max = PySequence_Size(pyObj); i < i_max; i++) { + PySequence_GetItem(pyObj, i); + } + } else { + Py_INCREF(pyObj); + } +} + +static void decRefPyObjectlist(const std::list<PyObject*> &lst) +{ + std::list<PyObject*>::const_iterator iter = lst.begin(); + while(iter != lst.end()) { + Py_DECREF(*iter); + iter++; + } +} + } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index d5a23939c..7403491f6 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -40,6 +40,7 @@ #include "bindingmanager.h" #include <list> #include <map> +#include <string> namespace Shiboken { @@ -48,7 +49,7 @@ namespace Shiboken * 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; +typedef std::map<std::string, std::list<PyObject*> > RefCountMap; extern "C" { @@ -237,7 +238,7 @@ SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); * \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 keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject); +LIBSHIBOKEN_API void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject, bool append=false); /// Returns true and sets a Python RuntimeError if the Python wrapper is not marked as valid. LIBSHIBOKEN_API bool cppObjectIsInvalid(PyObject* wrapper); |