]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/blockallocator.cpp
Don't continue reserving until the turnout is done changing its path
[r2c2.git] / source / libr2c2 / blockallocator.cpp
index b38b62d6d1f1cd37763fcb2c3979dff8d4e97439..022a8df230ee72e8e2185e36624ac13f5928b64b 100644 (file)
@@ -30,7 +30,8 @@ BlockAllocator::BlockAllocator(Train &t):
        cur_blocks_end(blocks.end()),
        pending_block(0),
        stop_at_block(0),
-       reserving(false)
+       reserving(false),
+       advancing(false)
 {
        Layout &layout = train.get_layout();
        layout.signal_block_reserved.connect(sigc::mem_fun(this, &BlockAllocator::block_reserved));
@@ -81,8 +82,8 @@ void BlockAllocator::rewind_to(const Block &block)
 
 void BlockAllocator::clear()
 {
-       active = false;
        release_blocks_begin(blocks.end());
+       active = false;
        pending_block = 0;
        stop_at_block = 0;
 }
@@ -151,7 +152,7 @@ void BlockAllocator::reserve_more()
        else if(&*start==pending_block)
        {
                TrackIter track = start.track_iter();
-               if(!track.endpoint().has_path(track->get_active_path()))
+               if(track->is_path_changing() || !track.endpoint().has_path(track->get_active_path()))
                        return;
        }
 
@@ -192,7 +193,10 @@ void BlockAllocator::reserve_more()
                }
 
                if(!reserve_block(block))
+               {
+                       pending_block = &*block;
                        break;
+               }
 
                if(cur_blocks_end==blocks.end())
                        --cur_blocks_end;
@@ -291,6 +295,8 @@ void BlockAllocator::release_blocks_end(const BlockList::iterator &begin)
 
 void BlockAllocator::release_block(const BlockList::iterator &i)
 {
+       if(advancing)
+               throw logic_error("cannot release while advancing");
        if(i==cur_blocks_end)
                ++cur_blocks_end;
        if(&**i==pending_block)
@@ -369,10 +375,14 @@ void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state)
 
                if(result==1)
                {
-                       // Move blocks up to the next sensor to our current blocks
-                       for(BlockList::iterator j=cur_blocks_end; j!=end; ++j)
-                               train.signal_advanced.emit(**j);
+                       /* Advance the train to the new blocks.  Update cur_blocks_end first
+                       to keep things in sync. */
+                       SetFlag setf(advancing);
+                       BlockList::iterator i = cur_blocks_end;
                        cur_blocks_end = end;
+                       for(; i!=end; ++i)
+                               train.signal_advanced.emit(**i);
+                       advancing = false;
 
                        if(active)
                                reserve_more();