App: make deleting dynamic property safer

Dynamic property can be removed at any time, even during triggering of
onChanged() signal of the removing property. This patch introduced
static function Property::destroy() to make it safer by queueing any
removed property, and only deleting them when no onChanged() call is
active.
This commit is contained in:
Zheng, Lei
2020-01-01 18:03:52 +08:00
committed by wmayer
parent 9860c741c8
commit d70ddf692e
4 changed files with 46 additions and 2 deletions

View File

@@ -138,8 +138,48 @@ ObjectIdentifier Property::canonicalPath(const ObjectIdentifier &p) const
return p;
}
static std::vector<Property*> _RemovedProps;
static int _PropCleanerCounter;
struct PropertyCleaner {
PropertyCleaner(Property *p)
: prop(p)
{
++_PropCleanerCounter;
}
~PropertyCleaner() {
if(--_PropCleanerCounter)
return;
bool found = false;
while(_RemovedProps.size()) {
auto p = _RemovedProps.back();
_RemovedProps.pop_back();
if(p != prop)
delete p;
else
found = true;
}
if(found)
_RemovedProps.push_back(prop);
}
Property *prop;
};
void Property::destroy(Property *p) {
if(p) {
// Is it necessary to nullify the container? May cause crash if any
// onChanged() caller assumes a non-null container.
//
// p->setContainer(0);
_RemovedProps.push_back(p);
}
}
void Property::touch()
{
PropertyCleaner guard(this);
if (father)
father->onChanged(this);
StatusBits.set(Touched);
@@ -152,6 +192,7 @@ void Property::setReadOnly(bool readOnly)
void Property::hasSetValue(void)
{
PropertyCleaner guard(this);
if (father)
father->onChanged(this);
StatusBits.set(Touched);