diff options
Diffstat (limited to 'sources/shiboken2/libshiboken/basewrapper.cpp')
-rw-r--r-- | sources/shiboken2/libshiboken/basewrapper.cpp | 318 |
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'; } |