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->_postCreate();
cdebug_log(110,1) << "Edge::create(): " << (void*)edge << ":" << edge << endl;
cdebug_log(110,0) << "source:" << (void*)source << ":" << edge->getSource() << endl;
cdebug_log(110,0) << "target:" << (void*)target << ":" << edge->getTarget() << 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) << "target:" << /*(void*)target << ":" <<*/ edge->getTarget() << endl;
cdebug_tabw(110,-1);
return edge;
}

View File

@ -192,7 +192,7 @@ stylesTable = \
, (Drawing, 'gmetalv' , { 'color':'200,200,255', 'pattern':'light_antihash1.8', '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::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") );
connect ( _stressDisplayAction, SIGNAL(triggered()), this, SLOT(stressDisplay()) );
debugMenu->addAction ( _stressDisplayAction );
//debugMenu->addAction ( _stressDisplayAction );
getCellWidget()->addDrawExtensionGo ( DemoGo::staticGetName()
, DemoGo::initDrawDemoGo

View File

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

View File

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

View File

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

View File

@ -226,25 +226,53 @@ namespace Hurricane {
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()) {
DBo* owner = *_ownerSet.begin();
_ownerSet.erase(owner);
owner->_onDestroyed(this);
// while (!_ownerSet.empty()) {
// DBo* owner = *_ownerSet.begin();
// _ownerSet.erase(owner);
// 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 )
{
_ownerSet.insert(owner);
for ( DBo* dbo : _ownerSet ) {
if (dbo == owner) return;
}
_ownerSet.push_back( owner );
//_ownerSet.insert(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();
}

View File

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

View File

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

View File

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