]> git.tdb.fi Git - r2c2.git/commitdiff
Improve block recreation algorithms
authorMikko Rasa <tdb@tdb.fi>
Mon, 19 Aug 2013 16:06:42 +0000 (19:06 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 19 Aug 2013 16:23:45 +0000 (19:23 +0300)
These changes result in a more than 100% performance improvement in
operations that create and delete a lot of tracks, such as the extend
tool.

source/libr2c2/layout.cpp
source/libr2c2/track.cpp

index b847637fab797481a34225ccf88dea9a2d29ceb4..f318958879ba16049741222428fa8cc32412de34 100644 (file)
@@ -255,26 +255,31 @@ Block &Layout::get_block(unsigned id) const
 
 void Layout::create_blocks()
 {
-       set<Track *> used_tracks;
+       set<Track *> loose_tracks = objects.get<Track>();
        const set<Block *> *blocks = &track_chains.get<Block>();
        for(set<Block *>::const_iterator i=blocks->begin(); i!=blocks->end(); ++i)
        {
                const set<Track *> &btracks = (*i)->get_tracks();
-               used_tracks.insert(btracks.begin(), btracks.end());
+               for(set<Track *>::const_iterator j=btracks.begin(); j!=btracks.end(); ++j)
+                       loose_tracks.erase(*j);
        }
 
-       const set<Track *> &tracks = objects.get<Track>();
-       for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               if(used_tracks.count(*i)==0)
-               {
-                       Block *block = new Block(*this, **i);
-                       used_tracks.insert(block->get_tracks().begin(), block->get_tracks().end());
-               }
+       list<Block *> created_blocks;
+       while(!loose_tracks.empty())
+       {
+               Block *block = new Block(*this, **loose_tracks.begin());
+               created_blocks.push_back(block);
+
+               const set<Track *> &btracks = block->get_tracks();
+               for(set<Track *>::const_iterator i=btracks.begin(); i!=btracks.end(); ++i)
+                       loose_tracks.erase(*i);
+       }
 
+       // The previously obtained set has been invalidated by creating new blocks
        blocks = &track_chains.get<Block>();
-       for(set<Block *>::iterator i=blocks->begin(); i!=blocks->end(); ++i)
-               for(set<Block *>::iterator j=i; j!=blocks->end(); ++j)
-                       if(j!=i)
+       for(list<Block *>::iterator i=created_blocks.begin(); i!=created_blocks.end(); ++i)
+               for(set<Block *>::const_iterator j=blocks->begin(); j!=blocks->end(); ++j)
+                       if(*j!=*i)
                                (*i)->check_link(**j);
 }
 
index 4708db5d40de6c79d26de28ef61af696afe6f48d..7a1746716574abdbedb40c0356042ae7932dba66 100644 (file)
@@ -344,9 +344,14 @@ bool Track::break_link(unsigned i)
                return false;
 
        links[i] = 0;
-       other->break_link(*this);
-       // XXX Creates the blocks twice, because the other track calls this too
-       layout.create_blocks(*this);
+       if(!other->break_link(*this))
+       {
+               /* If the call doesn't succeed, it means that the other track already
+               broke the link and is calling us right now.  Recreate blocks in the inner
+               call so it occurs before any signals are emitted. */
+               layout.create_blocks(*this);
+       }
+
        signal_link_changed.emit(i, 0);
 
        return true;