From: Mikko Rasa Date: Sun, 7 Jul 2013 21:59:27 +0000 (+0300) Subject: Refactor BlockAllocator to be more sensor-oriented X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=110a865e1a175f304ecaaa7a31b6985cf0c12a99;p=r2c2.git Refactor BlockAllocator to be more sensor-oriented This is necessary for soon-to-be implemented beam gate sensors. --- diff --git a/source/libr2c2/blockallocator.cpp b/source/libr2c2/blockallocator.cpp index fc2705c..215d746 100644 --- a/source/libr2c2/blockallocator.cpp +++ b/source/libr2c2/blockallocator.cpp @@ -28,6 +28,7 @@ struct BlockAllocator::BlockMatch BlockAllocator::BlockAllocator(Train &t): train(t), cur_blocks_end(blocks.end()), + next_sensor(0), pending_block(0), stop_at_block(0), reserving(false), @@ -84,6 +85,7 @@ void BlockAllocator::clear() { release_blocks_begin(blocks.end()); active = false; + next_sensor = 0; pending_block = 0; stop_at_block = 0; } @@ -241,9 +243,12 @@ void BlockAllocator::reserve_more() dist += block->get_path_length(block.entry()); } - // Make any sensorless blocks at the beginning immediately current - while(cur_blocks_end!=blocks.end() && !(*cur_blocks_end)->get_sensor_id()) - ++cur_blocks_end; + if(!next_sensor) + { + update_next_sensor(0); + // Immediately advance to just before the next sensor + advance_to(next_sensor ? next_sensor->get_block() : 0); + } } bool BlockAllocator::reserve_block(const BlockIter &block) @@ -268,6 +273,22 @@ bool BlockAllocator::reserve_block(const BlockIter &block) } } +void BlockAllocator::advance_to(const Block *block) +{ + BlockList::iterator end; + if(block) + end = find_if(cur_blocks_end, blocks.end(), BlockMatch(*block)); + else + end = blocks.end(); + + SetFlag setf(advancing); + BlockList::iterator i = cur_blocks_end; + // Update cur_blocks_end first to keep things consistent. + cur_blocks_end = end; + for(; i!=end; ++i) + train.signal_advanced.emit(**i); +} + void BlockAllocator::release_blocks_begin(const BlockList::iterator &end) { for(BlockList::iterator i=blocks.begin(); i!=end; ) @@ -299,6 +320,8 @@ void BlockAllocator::release_block(const BlockList::iterator &i) throw logic_error("cannot release while advancing"); if(i==cur_blocks_end) ++cur_blocks_end; + if(next_sensor && &**i==next_sensor->get_block()) + next_sensor = 0; if(&**i==pending_block) pending_block = 0; @@ -349,47 +372,21 @@ void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) if(state==Sensor::MAYBE_ACTIVE) { - // Find the first sensor block from our reserved blocks that isn't this sensor - BlockList::iterator end; - unsigned result = 0; - for(end=cur_blocks_end; end!=blocks.end(); ++end) - if((*end)->get_sensor_id()) - { - if(&**end!=block) - { - if(result==0) - result = 2; - else if(result==1) - break; - } - else if(result==0) - result = 1; - else if(result==2) - result = 3; - } - - if(result==1) + if(&sensor==next_sensor) { - /* 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; + update_next_sensor(next_sensor); + advance_to(next_sensor ? next_sensor->get_block() : 0); if(active) reserve_more(); } - else if(result==3) + else if(!is_block_current(*block)) train.get_layout().emergency("Sensor for "+train.get_name()+" triggered out of order"); } else if(state==Sensor::INACTIVE) { const Vehicle &veh = train.get_vehicle(train.get_controller().get_reverse() ? 0 : train.get_n_vehicles()-1); const Block &veh_block = veh.get_track()->get_block(); - const Driver &driver = train.get_layout().get_driver(); /* Sensors aren't guaranteed to be detriggered in order. Go through the block list and locate the first sensor that's still active. */ @@ -400,9 +397,9 @@ void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) if(&**i==&veh_block) break; - if((*i)->get_sensor_id()) + if(Sensor *s = (*i)->get_sensor()) { - if(driver.get_sensor((*i)->get_sensor_id())) + if(s->get_state()>=Sensor::MAYBE_INACTIVE) break; else end = i; @@ -415,6 +412,23 @@ void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) } } +void BlockAllocator::update_next_sensor(Sensor *after) +{ + BlockList::iterator i = cur_blocks_end; + if(after) + i = find_if(i, blocks.end(), BlockMatch(*after->get_block())); + + for(; i!=blocks.end(); ++i) + if(Sensor *sensor = (*i)->get_sensor()) + if(sensor!=next_sensor) + { + next_sensor = sensor; + return; + } + + next_sensor = 0; +} + void BlockAllocator::save(list &st) const { if(!blocks.empty() && cur_blocks_end!=blocks.begin()) diff --git a/source/libr2c2/blockallocator.h b/source/libr2c2/blockallocator.h index c0c265a..95cb910 100644 --- a/source/libr2c2/blockallocator.h +++ b/source/libr2c2/blockallocator.h @@ -36,6 +36,7 @@ private: bool active; BlockList blocks; BlockList::iterator cur_blocks_end; + Sensor *next_sensor; Block *pending_block; const Block *stop_at_block; bool reserving; @@ -64,6 +65,7 @@ public: private: void reserve_more(); bool reserve_block(const BlockIter &); + void advance_to(const Block *); void release_blocks_begin(const BlockList::iterator &); void release_blocks_end(const BlockList::iterator &); void release_block(const BlockList::iterator &); @@ -75,6 +77,7 @@ private: void turnout_path_changed(Track &); void block_reserved(Block &, const Train *); void sensor_state_changed(Sensor &, Sensor::State); + void update_next_sensor(Sensor *); public: void save(std::list &) const;