Deterministic destruction of Components.

* Change: In Hurrican::Component::_preDestroy(), the cascaded destruction
    of slaves Components and subsequent ring merge and Rubber creation
    was using set<> sorted on pointer values. This was making the order
    of destruction of the slaves components non-deterministic. Now the
    sets are sorted according to their id (see Entity).
* Change: In Hurricane::SharedProperty, the _ownerSet is now a vector<>
    instead of a set<>. This will slow the search process, but hopefully
    this is needed only during construction/destruction of a Property
    so the slow down shouldn't be too much.
      This has also an impact on Hurricane::Relation.
This commit is contained in:
Jean-Paul Chaput 2017-05-03 18:09:51 +02:00
parent 73a085308c
commit db8e51524f
10 changed files with 92 additions and 56 deletions

View File

@ -88,9 +88,9 @@ namespace Anabatic {
Edge* edge = new Edge ( source, target, flags ); Edge* edge = new Edge ( source, target, flags );
edge->_postCreate(); edge->_postCreate();
cdebug_log(110,1) << "Edge::create(): " << (void*)edge << ":" << edge << endl; cdebug_log(110,1) << "Edge::create(): " << /*(void*)edge << ":" <<*/ edge << endl;
cdebug_log(110,0) << "source:" << (void*)source << ":" << edge->getSource() << endl; cdebug_log(110,0) << "source:" << /*(void*)source << ":" <<*/ edge->getSource() << endl;
cdebug_log(110,0) << "target:" << (void*)target << ":" << edge->getTarget() << endl; cdebug_log(110,0) << "target:" << /*(void*)target << ":" <<*/ edge->getTarget() << endl;
cdebug_tabw(110,-1); cdebug_tabw(110,-1);
return edge; return edge;
} }

View File

@ -192,7 +192,7 @@ stylesTable = \
, (Drawing, 'gmetalv' , { 'color':'200,200,255', 'pattern':'light_antihash1.8', 'border':1 }) , (Drawing, 'gmetalv' , { 'color':'200,200,255', 'pattern':'light_antihash1.8', 'border':1 })
, (Drawing, 'gcut' , { 'color':'255,255,190', 'border':1 }) , (Drawing, 'gcut' , { 'color':'255,255,190', 'border':1 })
, (Drawing, 'Anabatic::Edge' , { 'color':'255,255,190', 'pattern':'0000000000000000', 'border':4, 'threshold':0.02*scale }) , (Drawing, 'Anabatic::Edge' , { 'color':'255,255,190', 'pattern':'0000000000000000', 'border':4, 'threshold':0.02*scale })
, (Drawing, 'Anabatic::GCell', { 'color':'128,128,128', 'pattern':'0000000000000000', 'border':4, 'threshold':0.10*scale }) , (Drawing, 'Anabatic::GCell', { 'color':'255,255,190', 'pattern':'0000000000000000', 'border':4, 'threshold':0.10*scale })
) )
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -77,7 +77,7 @@ namespace CRL {
_stressDisplayAction->setStatusTip ( tr("Intensive use of display redrawing") ); _stressDisplayAction->setStatusTip ( tr("Intensive use of display redrawing") );
connect ( _stressDisplayAction, SIGNAL(triggered()), this, SLOT(stressDisplay()) ); connect ( _stressDisplayAction, SIGNAL(triggered()), this, SLOT(stressDisplay()) );
debugMenu->addAction ( _stressDisplayAction ); //debugMenu->addAction ( _stressDisplayAction );
getCellWidget()->addDrawExtensionGo ( DemoGo::staticGetName() getCellWidget()->addDrawExtensionGo ( DemoGo::staticGetName()
, DemoGo::initDrawDemoGo , DemoGo::initDrawDemoGo

View File

@ -408,58 +408,50 @@ void Component::_postCreate()
void Component::_preDestroy() void Component::_preDestroy()
// ************************* // *************************
{ {
cdebug_log(18,1) << "entering Component::_Predestroy: " << this << endl; cdebug_log(18,1) << "entering Component::_preDestroy: " << this << endl;
clearProperties(); clearProperties();
set<Component*> componentSet; set<Component*,Entity::CompareById> components;
getSlaveComponents().fill(componentSet); getSlaveComponents().fill( components );
components.insert( this );
set<Hook*> masterHookSet; vector<Hook*> masterHooks;
componentSet.insert(this);
for_each_component(component, getCollection(componentSet)) { for ( Component* component : components ) {
component->unmaterialize(); component->unmaterialize();
for_each_hook(hook, component->getHooks()) { for ( Hook* chook : component->getHooks() ) {
for_each_hook(hook, hook->getHooks()) { for ( Hook* shook : chook->getHooks() ) {
if (hook->isMaster() && (componentSet.find(hook->getComponent()) == componentSet.end())) if (shook->isMaster() and (components.find(shook->getComponent()) == components.end()) )
masterHookSet.insert(hook); masterHooks.push_back( shook );
end_for;
} }
if (!hook->isMaster()) hook->detach(); if (not chook->isMaster()) chook->detach();
end_for;
} }
end_for;
} }
componentSet.erase(this); components.erase( this );
for_each_component(component, getCollection(componentSet)) { for ( Component* component : components ) component->destroy();
component->destroy();
end_for;
}
set<Rubber*> rubberSet; set<Rubber*,Entity::CompareById> rubbers;
set<Hook*> mainMasterHookSet; vector<Hook*> mainMasterHooks;
for_each_hook(hook, getCollection(masterHookSet)) {
Rubber* rubber = hook->getComponent()->getRubber(); for ( Hook* mhook : masterHooks ) {
if (!rubber) Rubber* rubber = mhook->getComponent()->getRubber();
mainMasterHookSet.insert(hook); if (not rubber)
mainMasterHooks.push_back( mhook );
else { else {
if (rubberSet.find(rubber) == rubberSet.end()) { if (rubbers.find(rubber) == rubbers.end()) {
rubberSet.insert(rubber); rubbers.insert( rubber );
mainMasterHookSet.insert(hook); mainMasterHooks.push_back( mhook );
} }
} }
end_for;
} }
Hook* masterHook = NULL; Hook* masterHook = NULL;
for_each_hook(hook, getCollection(mainMasterHookSet)) { for ( Hook* hook : mainMasterHooks ) {
if (!masterHook) if (not masterHook) masterHook = hook;
masterHook = hook; else hook->merge( masterHook );
else
hook->merge(masterHook);
end_for;
} }
/**/
_bodyHook.detach(); _bodyHook.detach();
@ -467,7 +459,6 @@ void Component::_preDestroy()
if (_net) _net->_getComponentSet()._remove(this); if (_net) _net->_getComponentSet()._remove(this);
cdebug_log(18,0) << "exiting Component::_Predestroy:" << endl; cdebug_log(18,0) << "exiting Component::_Predestroy:" << endl;
cdebug_tabw(18,-1); cdebug_tabw(18,-1);
} }

View File

@ -53,7 +53,9 @@ namespace Hurricane {
void DBo::_postCreate () void DBo::_postCreate ()
{ } {
cdebug_log(0,0) << "DBo::_postCreate() " << this << endl;
}
void DBo::_preDestroy () void DBo::_preDestroy ()
@ -64,7 +66,9 @@ namespace Hurricane {
void DBo::destroy () void DBo::destroy ()
{ {
cdebug_log(0,1) << "DBo::destroy() " << this << endl;
_preDestroy(); _preDestroy();
cdebug_tabw(0,-1);
delete this; delete this;
} }

View File

@ -362,6 +362,8 @@ Hook* Hook::merge(Hook* hook)
if (hook == this) if (hook == this)
throw Error("Can't merge : itself"); throw Error("Can't merge : itself");
cdebug_log(0,0) << "Hook::merge() hook:" << hook->getComponent() << endl;
Hook* masterHook = hook->getPreviousMasterHook(); Hook* masterHook = hook->getPreviousMasterHook();
Hook* nextHook = masterHook->_nextHook; Hook* nextHook = masterHook->_nextHook;
masterHook->_nextHook = _nextHook; masterHook->_nextHook = _nextHook;

View File

@ -226,25 +226,53 @@ namespace Hurricane {
void SharedProperty::_preDestroy () void SharedProperty::_preDestroy ()
{ {
Property::_preDestroy(); for ( size_t i=0 ; i<_ownerSet.size() ; ++i ) {
_ownerSet[i]->_onDestroyed(this);
_ownerSet[i] = NULL;
}
_ownerSet.clear();
while (!_ownerSet.empty()) { // while (!_ownerSet.empty()) {
DBo* owner = *_ownerSet.begin(); // DBo* owner = *_ownerSet.begin();
_ownerSet.erase(owner); // _ownerSet.erase(owner);
owner->_onDestroyed(this); // owner->_onDestroyed(this);
// }
Property::_preDestroy();
}
void SharedProperty::_erase ( DBo* owner )
{
for ( size_t i=0 ; i<_ownerSet.size() ; ++i ) {
if (_ownerSet[i] == owner) {
std::swap( _ownerSet[i], _ownerSet[_ownerSet.size()-1] );
_ownerSet.pop_back();
}
} }
} }
void SharedProperty::onCapturedBy ( DBo* owner ) void SharedProperty::onCapturedBy ( DBo* owner )
{ {
_ownerSet.insert(owner); for ( DBo* dbo : _ownerSet ) {
if (dbo == owner) return;
}
_ownerSet.push_back( owner );
//_ownerSet.insert(owner);
} }
void SharedProperty::onReleasedBy ( DBo* owner ) void SharedProperty::onReleasedBy ( DBo* owner )
{ {
_ownerSet.erase(owner); for ( size_t i=0 ; i<_ownerSet.size() ; ++i ) {
if (_ownerSet[i] == owner) {
std::swap( _ownerSet[i], _ownerSet[_ownerSet.size()-1] );
_ownerSet.pop_back();
}
}
//_ownerSet.erase(owner);
if (_ownerSet.empty()) onNotOwned(); if (_ownerSet.empty()) onNotOwned();
} }

View File

@ -99,7 +99,8 @@ DBos Relation::getSlaveOwners() const
void Relation::onReleasedBy(DBo* owner) void Relation::onReleasedBy(DBo* owner)
// ************************************ // ************************************
{ {
_getOwnerSet().erase(owner); _erase( owner );
//_getOwnerSet().erase(owner);
if (owner == _masterOwner) destroy(); if (owner == _masterOwner) destroy();
} }

View File

@ -433,14 +433,23 @@ template<class Element> class IntrusiveSet {
_length = newLength; _length = newLength;
_array = new Element*[_length]; _array = new Element*[_length];
memset(_array, 0, _length * sizeof(Element*)); memset(_array, 0, _length * sizeof(Element*));
cdebug_log(0,0) << "IntrusiveSet::_resize() " << oldLength << " -> " << newLength << endl;
for (unsigned index = 0; index < oldLength; index++) { for (unsigned index = 0; index < oldLength; index++) {
Element* element = oldArray[index]; Element* element = oldArray[index];
if (not element)
cdebug_log(0,0) << "| bucket:" << setw(4) << index << " empty" << endl;
while (element) { while (element) {
Element* nextElement = _getNextElement(element); Element* nextElement = _getNextElement(element);
unsigned newIndex = (_getHashValue(element) / 8) % _length; unsigned newIndex = (_getHashValue(element) / 8) % _length;
_setNextElement(element, _array[newIndex]); _setNextElement(element, _array[newIndex]);
_array[newIndex] = element; _array[newIndex] = element;
element = nextElement; element = nextElement;
cdebug_log(0,0) << "| bucket:" << setw(4) << index
<< " -> " << setw(4) << newIndex
<< " + " << element << endl;
} }
} }
delete[] oldArray; delete[] oldArray;

View File

@ -396,7 +396,7 @@ namespace Hurricane {
unsigned int _count; unsigned int _count;
}; };
public: public:
typedef set<DBo*> DBoSet; typedef vector<DBo*> DBoSet;
typedef map<string,Orphaned> OrphanedMap; typedef map<string,Orphaned> OrphanedMap;
public: public:
static const OrphanedMap& getOrphaneds (); static const OrphanedMap& getOrphaneds ();
@ -411,6 +411,7 @@ namespace Hurricane {
virtual void onCapturedBy ( DBo* owner ); virtual void onCapturedBy ( DBo* owner );
virtual void onReleasedBy ( DBo* owner ); virtual void onReleasedBy ( DBo* owner );
virtual void onNotOwned (); virtual void onNotOwned ();
void _erase ( DBo* owner );
inline DBoSet& _getOwnerSet (); inline DBoSet& _getOwnerSet ();
virtual string _getString () const; virtual string _getString () const;
virtual Record* _getRecord () const; virtual Record* _getRecord () const;