aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken/basewrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp318
1 files changed, 145 insertions, 173 deletions
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 0aba26679..2b27f2881 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -60,6 +60,15 @@ namespace {
void _destroyParentInfo(SbkObject* obj, bool keepReference);
}
+static void callDestructor(const Shiboken::DtorAccumulatorVisitor::DestructorEntries &dts)
+{
+ for (const auto &e : dts) {
+ Shiboken::ThreadStateSaver threadSaver;
+ threadSaver.save();
+ e.destructor(e.cppInstance);
+ }
+}
+
extern "C"
{
@@ -118,20 +127,15 @@ static int SbkObject_traverse(PyObject* self, visitproc visit, void* arg)
//Visit children
Shiboken::ParentInfo* pInfo = sbkSelf->d->parentInfo;
if (pInfo) {
- std::set<SbkObject*>::const_iterator it = pInfo->children.begin();
- for(; it != pInfo->children.end(); ++it)
- Py_VISIT(*it);
+ for (SbkObject *c : pInfo->children)
+ Py_VISIT(c);
}
//Visit refs
Shiboken::RefCountMap* rInfo = sbkSelf->d->referredObjects;
if (rInfo) {
- Shiboken::RefCountMap::const_iterator it = rInfo->begin();
- for (; it != rInfo->end(); ++it) {
- std::list<PyObject*>::const_iterator ref = it->second.begin();
- for(; ref != it->second.end(); ++ref)
- Py_VISIT(*ref);
- }
+ for (auto it = rInfo->begin(), end = rInfo->end(); it != end; ++it)
+ Py_VISIT(it->second);
}
if (sbkSelf->ob_dict)
@@ -217,8 +221,10 @@ static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete)
if (canDelete && sbkObj->d->hasOwnership && sbkObj->d->validCppObject) {
SbkObjectTypePrivate *sotp = PepType_SOTP(pyType);
if (sotp->is_multicpp) {
- Shiboken::DeallocVisitor visitor(sbkObj);
+ Shiboken::DtorAccumulatorVisitor visitor(sbkObj);
Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor);
+ Shiboken::Object::deallocData(sbkObj, true);
+ callDestructor(visitor.entries());
} else {
void* cptr = sbkObj->d->cptr[0];
Shiboken::Object::deallocData(sbkObj, true);
@@ -325,7 +331,7 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k
Shiboken::ObjectType::initPrivateData(newType);
SbkObjectTypePrivate *sotp = PepType_SOTP(newType);
- std::list<SbkObjectType*> bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject*>(newType));
+ const auto bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject*>(newType));
if (bases.size() == 1) {
SbkObjectTypePrivate *parentType = PepType_SOTP(bases.front());
sotp->mi_offsets = parentType->mi_offsets;
@@ -352,10 +358,9 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k
sotp->d_func = nullptr;
sotp->is_user_type = 1;
- std::list<SbkObjectType*>::const_iterator it = bases.begin();
- for (; it != bases.end(); ++it) {
- if (PepType_SOTP(*it)->subtype_init)
- PepType_SOTP(*it)->subtype_init(newType, args, kwds);
+ for (SbkObjectType *base : bases) {
+ if (PepType_SOTP(base)->subtype_init)
+ PepType_SOTP(base)->subtype_init(newType, args, kwds);
}
return reinterpret_cast<PyObject*>(newType);
@@ -453,37 +458,22 @@ void _destroyParentInfo(SbkObject* obj, bool keepReference)
namespace Shiboken
{
-
-static void decRefPyObjectList(const std::list<PyObject*> &pyObj, PyObject* skip = 0);
-
-static void _walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor)
+bool walkThroughClassHierarchy(PyTypeObject *currentType, HierarchyVisitor *visitor)
{
PyObject* bases = currentType->tp_bases;
Py_ssize_t numBases = PyTuple_GET_SIZE(bases);
- for (int i = 0; i < numBases; ++i) {
+ bool result = false;
+ for (int i = 0; !result && i < numBases; ++i) {
PyTypeObject* type = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
-
- if (!PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))) {
- continue;
- } else {
+ if (PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(SbkObject_TypeF()))) {
SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(type);
- if (PepType_SOTP(sbkType)->is_user_type)
- _walkThroughClassHierarchy(type, visitor);
- else
- visitor->visit(sbkType);
+ result = PepType_SOTP(sbkType)->is_user_type
+ ? walkThroughClassHierarchy(type, visitor) : visitor->visit(sbkType);
}
- if (visitor->wasFinished())
- break;
}
+ return result;
}
-void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor)
-{
- _walkThroughClassHierarchy(currentType, visitor);
- visitor->done();
-}
-
-
bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr)
{
PyObject* sysModules = PyImport_GetModuleDict();
@@ -515,25 +505,32 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr)
// Wrapper metatype and base type ----------------------------------------------------------
-void DtorCallerVisitor::visit(SbkObjectType* node)
+HierarchyVisitor::HierarchyVisitor() = default;
+HierarchyVisitor::~HierarchyVisitor() = default;
+
+bool BaseCountVisitor::visit(SbkObjectType *)
{
- m_ptrs.push_back(std::make_pair(m_pyObj->d->cptr[m_ptrs.size()], node));
+ m_count++;
+ return false;
}
-void DtorCallerVisitor::done()
+bool BaseAccumulatorVisitor::visit(SbkObjectType *node)
{
- std::list<std::pair<void*, SbkObjectType*> >::const_iterator it = m_ptrs.begin();
- for (; it != m_ptrs.end(); ++it) {
- Shiboken::ThreadStateSaver threadSaver;
- threadSaver.save();
- PepType_SOTP(it->second)->cpp_dtor(it->first);
- }
+ m_bases.push_back(node);
+ return false;
}
-void DeallocVisitor::done()
+bool GetIndexVisitor::visit(SbkObjectType *node)
{
- Shiboken::Object::deallocData(m_pyObj, true);
- DtorCallerVisitor::done();
+ m_index++;
+ return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(node), m_desiredType);
+}
+
+bool DtorAccumulatorVisitor::visit(SbkObjectType *node)
+{
+ m_entries.push_back(DestructorEntry{PepType_SOTP(node)->cpp_dtor,
+ m_pyObject->d->cptr[m_entries.size()]});
+ return false;
}
namespace Conversions { void init(); }
@@ -607,25 +604,21 @@ void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const cha
class FindBaseTypeVisitor : public HierarchyVisitor
{
- public:
- FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {}
- virtual void visit(SbkObjectType* node)
- {
- if (reinterpret_cast<PyTypeObject*>(node) == m_typeToFind) {
- m_found = true;
- finish();
- }
- }
- bool found() const { return m_found; }
+public:
+ explicit FindBaseTypeVisitor(PyTypeObject *typeToFind) : m_typeToFind(typeToFind) {}
- private:
- bool m_found;
- PyTypeObject* m_typeToFind;
+ bool visit(SbkObjectType *node) override
+ {
+ return reinterpret_cast<PyTypeObject*>(node) == m_typeToFind;
+ }
+
+private:
+ PyTypeObject *m_typeToFind;
};
-std::list<SbkObject*> splitPyObject(PyObject* pyObj)
+std::vector<SbkObject *> splitPyObject(PyObject* pyObj)
{
- std::list<SbkObject*> result;
+ std::vector<SbkObject *> result;
if (PySequence_Check(pyObj)) {
AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object."));
if (!lst.isNull()) {
@@ -641,14 +634,11 @@ std::list<SbkObject*> splitPyObject(PyObject* pyObj)
return result;
}
-static void decRefPyObjectList(const std::list<PyObject*>& lst, PyObject *skip)
+template <class Iterator>
+inline void decRefPyObjectList(Iterator i1, Iterator i2)
{
- std::list<PyObject*>::const_iterator iter = lst.begin();
- while(iter != lst.end()) {
- if (*iter != skip)
- Py_DECREF(*iter);
- ++iter;
- }
+ for (; i1 != i2; ++i1)
+ Py_DECREF(i1->second);
}
namespace ObjectType
@@ -667,8 +657,7 @@ bool isUserType(PyTypeObject* type)
bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType)
{
FindBaseTypeVisitor visitor(ctorType);
- walkThroughClassHierarchy(myType, &visitor);
- if (!visitor.found()) {
+ if (!walkThroughClassHierarchy(myType, &visitor)) {
PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name);
return false;
}
@@ -842,12 +831,13 @@ static void setSequenceOwnership(PyObject* pyObj, bool owner)
if (PySequence_Check(pyObj) && has_length) {
Py_ssize_t size = PySequence_Size(pyObj);
if (size > 0) {
- std::list<SbkObject*> objs = splitPyObject(pyObj);
- for (auto it = objs.begin(), end = objs.end(); it != end; ++it) {
- if (owner)
- getOwnership(*it);
- else
- releaseOwnership(*it);
+ const auto objs = splitPyObject(pyObj);
+ if (owner) {
+ for (SbkObject *o : objs)
+ getOwnership(o);
+ } else {
+ for (SbkObject *o : objs)
+ releaseOwnership(o);
}
}
} else if (Object::checkType(pyObj)) {
@@ -883,8 +873,9 @@ void callCppDestructors(SbkObject* pyObj)
PyTypeObject *type = Py_TYPE(pyObj);
SbkObjectTypePrivate * sotp = PepType_SOTP(type);
if (sotp->is_multicpp) {
- Shiboken::DtorCallerVisitor visitor(pyObj);
+ Shiboken::DtorAccumulatorVisitor visitor(pyObj);
Shiboken::walkThroughClassHierarchy(type, &visitor);
+ callDestructor(visitor.entries());
} else {
Shiboken::ThreadStateSaver threadSaver;
threadSaver.save();
@@ -975,10 +966,9 @@ void invalidate(SbkObject* self)
static void recursive_invalidate(PyObject* pyobj, std::set<SbkObject*>& seen)
{
- std::list<SbkObject*> objs = splitPyObject(pyobj);
- std::list<SbkObject*>::const_iterator it = objs.begin();
- for (; it != objs.end(); it++)
- recursive_invalidate(*it, seen);
+ const auto objs = splitPyObject(pyobj);
+ for (SbkObject *o : objs)
+ recursive_invalidate(o, seen);
}
static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen)
@@ -997,30 +987,22 @@ static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen)
if (self->d->parentInfo) {
// Create a copy because this list can be changed during the process
ChildrenList copy = self->d->parentInfo->children;
- ChildrenList::iterator it = copy.begin();
- for (; it != copy.end(); ++it) {
+ for (SbkObject *child : copy) {
// invalidate the child
- recursive_invalidate(*it, seen);
+ recursive_invalidate(child, seen);
// if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed
if (!self->d->validCppObject)
- removeParent(*it, true, true);
+ removeParent(child, true, true);
}
}
// If has ref to other objects invalidate all
if (self->d->referredObjects) {
RefCountMap& refCountMap = *(self->d->referredObjects);
- RefCountMap::iterator iter;
- for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) {
- const std::list<PyObject*> lst = iter->second;
- std::list<PyObject*>::const_iterator it = lst.begin();
- while(it != lst.end()) {
- recursive_invalidate(*it, seen);
- ++it;
- }
- }
+ for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it)
+ recursive_invalidate(it->second, seen);
}
}
@@ -1035,23 +1017,17 @@ void makeValid(SbkObject* self)
// If it is a parent make all children valid
if (self->d->parentInfo) {
- ChildrenList::iterator it = self->d->parentInfo->children.begin();
- for (; it != self->d->parentInfo->children.end(); ++it)
- makeValid(*it);
+ for (SbkObject *child : self->d->parentInfo->children)
+ makeValid(child);
}
// If has ref to other objects make all valid again
if (self->d->referredObjects) {
RefCountMap& refCountMap = *(self->d->referredObjects);
RefCountMap::iterator iter;
- for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) {
- const std::list<PyObject*> lst = iter->second;
- std::list<PyObject*>::const_iterator it = lst.begin();
- while(it != lst.end()) {
- if (Shiboken::Object::checkType(*it))
- makeValid(reinterpret_cast<SbkObject*>(*it));
- ++it;
- }
+ for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it) {
+ if (Shiboken::Object::checkType(it->second))
+ makeValid(reinterpret_cast<SbkObject *>(it->second));
}
}
}
@@ -1166,15 +1142,14 @@ SbkObject *findColocatedChild(SbkObject *wrapper,
ChildrenList& children = pInfo->children;
- ChildrenList::iterator childrenEnd = children.end();
- for (ChildrenList::iterator iChild = children.begin(); iChild != childrenEnd; ++iChild) {
- if (!((*iChild)->d && (*iChild)->d->cptr))
+ for (SbkObject *child : children) {
+ if (!(child->d && child->d->cptr))
continue;
- if ((*iChild)->d->cptr[0] == wrapper->d->cptr[0]) {
- if (reinterpret_cast<const void *>(Py_TYPE(*iChild)) == reinterpret_cast<const void *>(instanceType))
- return const_cast<SbkObject *>((*iChild));
+ if (child->d->cptr[0] == wrapper->d->cptr[0]) {
+ if (reinterpret_cast<const void *>(Py_TYPE(child)) == reinterpret_cast<const void *>(instanceType))
+ return child;
else
- return findColocatedChild(const_cast<SbkObject *>(*iChild), instanceType);
+ return findColocatedChild(child, instanceType);
}
}
return 0;
@@ -1433,57 +1408,56 @@ void* getTypeUserData(SbkObject* wrapper)
return PepType_SOTP(Py_TYPE(wrapper))->user_data;
}
-void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append)
+static inline bool isNone(const PyObject *o)
{
- bool isNone = (!referredObject || (referredObject == Py_None));
-
- if (!self->d->referredObjects)
- self->d->referredObjects = new Shiboken::RefCountMap;
-
- RefCountMap& refCountMap = *(self->d->referredObjects);
- RefCountMap::iterator iter = refCountMap.find(key);
- std::list<PyObject*> objects;
- if (iter != refCountMap.end()) {
- objects = (*iter).second;
- std::list<PyObject*>::const_iterator found = std::find(objects.begin(), objects.end(), referredObject);
-
- // skip if objects already exists
- if (found != objects.end())
- return;
- }
+ return o == nullptr || o == Py_None;
+}
- if (append && !isNone) {
- refCountMap[key].push_back(referredObject);
- Py_INCREF(referredObject);
- } else if (!append) {
- if (objects.size() > 0)
- decRefPyObjectList(objects, isNone ? 0 : referredObject);
- if (isNone) {
- if (iter != refCountMap.end())
- refCountMap.erase(iter);
- } else {
- objects.clear();
- objects.push_back(referredObject);
- refCountMap[key] = objects;
- Py_INCREF(referredObject);
+static void removeRefCountKey(SbkObject* self, const char *key)
+{
+ if (self->d->referredObjects) {
+ const auto iterPair = self->d->referredObjects->equal_range(key);
+ if (iterPair.first != iterPair.second) {
+ decRefPyObjectList(iterPair.first, iterPair.second);
+ self->d->referredObjects->erase(iterPair.first, iterPair.second);
}
}
}
-void removeReference(SbkObject* self, const char* key, PyObject* referredObject)
+void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append)
{
- if (!referredObject || (referredObject == Py_None))
+ if (isNone(referredObject)) {
+ removeRefCountKey(self, key);
return;
+ }
- if (!self->d->referredObjects)
+ if (!self->d->referredObjects) {
+ self->d->referredObjects =
+ new Shiboken::RefCountMap{RefCountMap::value_type{key, referredObject}};
+ Py_INCREF(referredObject);
return;
+ }
RefCountMap& refCountMap = *(self->d->referredObjects);
- RefCountMap::iterator iter = refCountMap.find(key);
- if (iter != refCountMap.end()) {
- decRefPyObjectList(iter->second);
- refCountMap.erase(iter);
+ const auto iterPair = refCountMap.equal_range(key);
+ if (std::any_of(iterPair.first, iterPair.second,
+ [referredObject](const RefCountMap::value_type &v) { return v.second == referredObject; })) {
+ return;
}
+
+ if (!append && iterPair.first != iterPair.second) {
+ decRefPyObjectList(iterPair.first, iterPair.second);
+ refCountMap.erase(iterPair.first, iterPair.second);
+ }
+
+ refCountMap.insert(RefCountMap::value_type{key, referredObject});
+ Py_INCREF(referredObject);
+}
+
+void removeReference(SbkObject* self, const char* key, PyObject* referredObject)
+{
+ if (!isNone(referredObject))
+ removeRefCountKey(self, key);
}
void clearReferences(SbkObject* self)
@@ -1492,27 +1466,27 @@ void clearReferences(SbkObject* self)
return;
RefCountMap& refCountMap = *(self->d->referredObjects);
- RefCountMap::iterator iter;
- for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter)
- decRefPyObjectList(iter->second);
+ for (auto it = refCountMap.begin(), end = refCountMap.end(); it != end; ++it)
+ Py_DECREF(it->second);
self->d->referredObjects->clear();
}
std::string info(SbkObject* self)
{
std::ostringstream s;
- std::list<SbkObjectType*> bases;
if (self->d && self->d->cptr) {
+ std::vector<SbkObjectType *> bases;
if (ObjectType::isUserType(Py_TYPE(self)))
bases = getCppBaseClasses(Py_TYPE(self));
else
bases.push_back(reinterpret_cast<SbkObjectType*>(Py_TYPE(self)));
s << "C++ address....... ";
- std::list<SbkObjectType*>::const_iterator it = bases.begin();
- for (int i = 0; it != bases.end(); ++it, ++i)
- s << reinterpret_cast<PyTypeObject *>(*it)->tp_name << '/' << self->d->cptr[i] << ' ';
+ for (size_t i = 0, size = bases.size(); i < size; ++i) {
+ auto base = reinterpret_cast<PyTypeObject *>(bases[i]);
+ s << base->tp_name << '/' << self->d->cptr[i] << ' ';
+ }
s << "\n";
}
else {
@@ -1533,9 +1507,8 @@ std::string info(SbkObject* self)
if (self->d->parentInfo && !self->d->parentInfo->children.empty()) {
s << "children.......... ";
- ChildrenList& children = self->d->parentInfo->children;
- for (ChildrenList::const_iterator it = children.begin(); it != children.end(); ++it) {
- Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast<PyObject *>(*it)));
+ for (SbkObject *sbkChild : self->d->parentInfo->children) {
+ Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast<PyObject *>(sbkChild)));
s << String::toCString(child) << ' ';
}
s << '\n';
@@ -1544,17 +1517,16 @@ std::string info(SbkObject* self)
if (self->d->referredObjects && !self->d->referredObjects->empty()) {
Shiboken::RefCountMap& map = *self->d->referredObjects;
s << "referred objects.. ";
- Shiboken::RefCountMap::const_iterator it = map.begin();
- for (; it != map.end(); ++it) {
- if (it != map.begin())
- s << " ";
- s << '"' << it->first << "\" => ";
- std::list<PyObject*>::const_iterator j = it->second.begin();
- for (; j != it->second.end(); ++j) {
- Shiboken::AutoDecRef obj(PyObject_Str(*j));
- s << String::toCString(obj) << ' ';
+ std::string lastKey;
+ for (auto it = map.begin(), end = map.end(); it != end; ++it) {
+ if (it->first != lastKey) {
+ if (!lastKey.empty())
+ s << " ";
+ s << '"' << it->first << "\" => ";
+ lastKey = it->first;
}
- s << ' ';
+ Shiboken::AutoDecRef obj(PyObject_Str(it->second));
+ s << String::toCString(obj) << ' ';
}
s << '\n';
}