aboutsummaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2010-07-09 15:29:30 -0300
committerRenato Filho <renato.filho@openbossa.org>2010-07-09 19:26:16 -0300
commit4807359481f136145f404421ab8e99dd5f4cfefd (patch)
treebf5c7a71223e65b771cc99f5eee328a9c189745a /libshiboken
parentc740aa812e6556747c51f2ac117c7107739aacab (diff)
Use list on keep reference map.
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'libshiboken')
-rw-r--r--libshiboken/basewrapper.cpp56
-rw-r--r--libshiboken/basewrapper.h5
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);