From: Mikko Rasa Date: Sat, 30 Oct 2010 19:50:14 +0000 (+0000) Subject: Use a single block list in Train X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=c18c79f72c065933b00c6092d9d5054f9e82b8df;p=r2c2.git Use a single block list in Train --- diff --git a/source/libmarklin/train.cpp b/source/libmarklin/train.cpp index f901540..23c4b52 100644 --- a/source/libmarklin/train.cpp +++ b/source/libmarklin/train.cpp @@ -46,6 +46,7 @@ Train::Train(Layout &l, const VehicleType &t, unsigned a): address(a), priority(0), yielding_to(0), + cur_blocks_end(blocks.end()), pending_block(0), reserving(false), advancing(false), @@ -209,10 +210,10 @@ bool Train::set_route(const Route *r) free_noncritical_blocks(); Route *lead = 0; - if(r && !cur_blocks.empty()) + if(r && !blocks.empty()) { - TrackIter first = cur_blocks.front().track_iter(); - TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter(); + TrackIter first = blocks.front().track_iter(); + TrackIter next = blocks.back().next().track_iter(); if(!r->has_track(*next)) { lead = Route::find(next, *r); @@ -241,7 +242,7 @@ bool Train::set_route(const Route *r) bool Train::go_to(Track &to) { - for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i) + for(BlockList::const_iterator i=blocks.begin(); i!=cur_blocks_end; ++i) if((*i)->has_track(to)) { signal_arrived.emit(); @@ -250,7 +251,7 @@ bool Train::go_to(Track &to) free_noncritical_blocks(); - TrackIter next = (rsv_blocks.empty() ? cur_blocks : rsv_blocks).back().next().track_iter(); + TrackIter next = blocks.back().next().track_iter(); Route *route = Route::find(next, to); if(!route) @@ -271,7 +272,7 @@ bool Train::divert(Track &from) list::iterator route = routes.begin(); // Follow our routes to find out where we're entering the turnout - for(TrackLoopIter track = cur_blocks.back().track_iter();;) + for(TrackLoopIter track = blocks.front().track_iter();;) { if(!advance_route(route, *track)) return false; @@ -366,8 +367,7 @@ void Train::place(Block &block, unsigned entry) if(controller->get_speed()) throw InvalidState("Must be stopped before placing"); - release_blocks(rsv_blocks); - release_blocks(cur_blocks); + release_blocks(); set_active(false); accurate_position = false; @@ -378,7 +378,7 @@ void Train::place(Block &block, unsigned entry) return; } - cur_blocks.push_back(BlockIter(&block, entry)); + blocks.push_back(BlockIter(&block, entry)); if(reverse) { TrackIter track = BlockIter(&block, entry).reverse().track_iter(); @@ -396,8 +396,7 @@ void Train::unplace() if(controller->get_speed()) throw InvalidState("Must be stopped before unplacing"); - release_blocks(rsv_blocks); - release_blocks(cur_blocks); + release_blocks(); set_active(false); accurate_position = false; @@ -415,13 +414,13 @@ bool Train::free_block(Block &block) return false; unsigned nsens = 0; - for(BlockList::iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + for(BlockList::iterator i=cur_blocks_end; i!=blocks.end(); ++i) { if(i->block()==&block) { if(nsens<1) return false; - release_blocks(rsv_blocks, i, rsv_blocks.end()); + release_blocks(i, blocks.end()); return true; } else if((*i)->get_sensor_id()) @@ -433,12 +432,12 @@ bool Train::free_block(Block &block) void Train::free_noncritical_blocks() { - if(cur_blocks.empty() || rsv_blocks.empty()) + if(blocks.empty()) return; if(controller->get_speed()==0) { - release_blocks(rsv_blocks); + release_blocks(cur_blocks_end, blocks.end()); return; } @@ -448,16 +447,13 @@ void Train::free_noncritical_blocks() Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front()); TrackIter track(veh.get_track(), veh.get_entry()); - BlockList::iterator block = cur_blocks.begin(); + BlockList::iterator block = blocks.begin(); bool in_rsv = false; - while(block!=rsv_blocks.end() && !(*block)->has_track(*track)) + while(block!=blocks.end() && !(*block)->has_track(*track)) { ++block; - if(block==cur_blocks.end()) - { - block = rsv_blocks.begin(); + if(block==cur_blocks_end) in_rsv = true; - } } float dist = veh.get_offset(); @@ -475,17 +471,14 @@ void Train::free_noncritical_blocks() if(!(*block)->has_track(*track)) { ++block; - if(block==cur_blocks.end()) - { - block = rsv_blocks.begin(); + if(block==cur_blocks_end) in_rsv = true; - } - if(block==rsv_blocks.end()) + if(block==blocks.end()) return; if(dist>min_dist && nsens>0) { - release_blocks(rsv_blocks, block, rsv_blocks.end()); + release_blocks(block, blocks.end()); return; } @@ -499,10 +492,7 @@ void Train::free_noncritical_blocks() int Train::get_entry_to_block(Block &block) const { - for(BlockList::const_iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i) - if(i->block()==&block) - return i->entry(); - for(BlockList::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + for(BlockList::const_iterator i=blocks.begin(); i!=blocks.end(); ++i) if(i->block()==&block) return i->entry(); return -1; @@ -517,7 +507,7 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) { if(!active && stop_timeout && t>=stop_timeout) { - release_blocks(rsv_blocks); + release_blocks(cur_blocks_end, blocks.end()); end_of_route = false; stop_timeout = Time::TimeStamp(); } @@ -535,8 +525,8 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) reverse = controller->get_reverse(); driver.set_loco_reverse(address, reverse); - release_blocks(rsv_blocks); - reverse_blocks(cur_blocks); + release_blocks(cur_blocks_end, blocks.end()); + reverse_blocks(blocks); reserve_more(); } @@ -562,7 +552,7 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) Track *track = vehicle.get_track(); bool ok = false; - for(BlockList::const_iterator i=cur_blocks.begin(); (!ok && i!=cur_blocks.end()); ++i) + for(BlockList::const_iterator i=blocks.begin(); (!ok && i!=cur_blocks_end); ++i) ok = (*i)->has_track(*track); float d = get_real_speed(current_speed)*(dt/Time::sec); @@ -581,21 +571,21 @@ void Train::tick(const Time::TimeStamp &t, const Time::TimeDelta &dt) } } } - else if(end_of_route && rsv_blocks.empty()) + else if(end_of_route && cur_blocks_end==blocks.end()) { set_active(false); signal_arrived.emit(); set_route(0); } - if(!cur_blocks.empty() && !cur_blocks.front()->get_sensor_id()) + if(!blocks.empty() && !blocks.front()->get_sensor_id()) { - float dist = get_reserved_distance_until(&*cur_blocks.front(), true); + float dist = get_reserved_distance_until(&*blocks.front(), true); if(dist>10*layout.get_catalogue().get_scale()) { - cur_blocks.front()->reserve(0); - cur_blocks.pop_front(); + blocks.front()->reserve(0); + blocks.pop_front(); } } } @@ -614,16 +604,16 @@ void Train::save(list &st) const if(real_speed[i].weight) st.push_back((DataFile::Statement("real_speed"), i, real_speed[i].speed, real_speed[i].weight)); - if(!cur_blocks.empty()) + if(!blocks.empty() && cur_blocks_end!=blocks.begin()) { - BlockList blocks = cur_blocks; + BlockList blks(blocks.begin(), BlockList::const_iterator(cur_blocks_end)); if(reverse) - reverse_blocks(blocks); + reverse_blocks(blks); - BlockIter prev = blocks.front().flip(); + BlockIter prev = blks.front().flip(); st.push_back((DataFile::Statement("block_hint"), prev->get_id())); - for(BlockList::const_iterator i=blocks.begin(); i!=blocks.end(); ++i) + for(BlockList::const_iterator i=blks.begin(); i!=blks.end(); ++i) st.push_back((DataFile::Statement("block"), (*i)->get_id())); } @@ -678,12 +668,12 @@ void Train::sensor_event(unsigned addr, bool state) if(state) { // Find the first sensor block from our reserved blocks that isn't this sensor - BlockList::iterator i; + BlockList::iterator end; unsigned result = 0; - for(i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) - if((*i)->get_sensor_id()) + for(end=cur_blocks_end; end!=blocks.end(); ++end) + if((*end)->get_sensor_id()) { - if((*i)->get_sensor_id()!=addr) + if((*end)->get_sensor_id()!=addr) { if(result==0) result = 2; @@ -696,7 +686,7 @@ void Train::sensor_event(unsigned addr, bool state) result = 3; } - if(result==1 && i!=rsv_blocks.begin()) + if(result==1) { // Compute speed and update related state float travel_time_secs = (Time::now()-last_entry_time)/Time::sec; @@ -712,7 +702,7 @@ void Train::sensor_event(unsigned addr, bool state) } travel_dist = 0; - for(BlockList::iterator j=rsv_blocks.begin(); j!=i; ++j) + for(BlockList::iterator j=cur_blocks_end; j!=end; ++j) { travel_dist += (*j)->get_path_length(j->entry()); @@ -737,7 +727,7 @@ void Train::sensor_event(unsigned addr, bool state) if(routes.size()>1) { const set &rtracks = (++routes.begin())->route->get_tracks(); - for(BlockList::iterator j=rsv_blocks.begin(); j!=i; ++j) + for(BlockList::iterator j=cur_blocks_end; j!=end; ++j) if(rtracks.count((*j)->get_endpoints()[j->entry()].track)) { routes.pop_front(); @@ -748,7 +738,7 @@ void Train::sensor_event(unsigned addr, bool state) } // Move blocks up to the next sensor to our current blocks - cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i); + cur_blocks_end = end; // Try to get more blocks if we're moving if(active) @@ -762,8 +752,8 @@ void Train::sensor_event(unsigned addr, bool state) const Vehicle &veh = *(reverse ? vehicles.front() : vehicles.back()); // Find the first sensor in our current blocks that's still active - BlockList::iterator end = cur_blocks.begin(); - for(BlockList::iterator i=cur_blocks.begin(); i!=cur_blocks.end(); ++i) + BlockList::iterator end = blocks.begin(); + for(BlockList::iterator i=blocks.begin(); i!=cur_blocks_end; ++i) { if((*i)->has_track(*veh.get_track())) break; @@ -779,9 +769,9 @@ void Train::sensor_event(unsigned addr, bool state) } } - if(end!=cur_blocks.begin() && end!=cur_blocks.end()) + if(end!=blocks.begin() && end!=cur_blocks_end) // Free blocks up to the last inactive sensor - release_blocks(cur_blocks, cur_blocks.begin(), end); + release_blocks(blocks.begin(), end); } } @@ -815,23 +805,17 @@ void Train::block_reserved(const Block &block, const Train *train) unsigned Train::reserve_more() { - if(!active) + if(!active || blocks.empty()) return 0; - BlockIter start; - if(!rsv_blocks.empty()) - start = rsv_blocks.back(); - else if(!cur_blocks.empty()) - start = cur_blocks.back(); - else - return 0; + BlockIter start = blocks.back(); pending_block = 0; // See how many sensor blocks and how much track we already have unsigned nsens = 0; float dist = 0; - for(BlockList::const_iterator i=rsv_blocks.begin(); i!=rsv_blocks.end(); ++i) + for(BlockList::const_iterator i=cur_blocks_end; i!=blocks.end(); ++i) { if((*i)->get_sensor_id()) ++nsens; @@ -904,7 +888,7 @@ unsigned Train::reserve_more() if(blocking_train->free_block(*contested_blocks.back())) { // Roll back and start actually reserving the blocks - block = rsv_blocks.back(); + block = blocks.back(); cur_route = routes.begin(); advance_route(cur_route, *block.track_iter().track()); if(blocking_train->get_priority()==priority) @@ -1031,7 +1015,9 @@ unsigned Train::reserve_more() if(!contested_blocks.empty() && contested_blocks.front()==block) contested_blocks.pop_front(); - rsv_blocks.push_back(block); + blocks.push_back(block); + if(cur_blocks_end==blocks.end()) + --cur_blocks_end; if(block->get_sensor_id()) ++nsens; if(nsens>0) @@ -1039,21 +1025,21 @@ unsigned Train::reserve_more() } // Unreserve blocks that were not good - while(!rsv_blocks.empty() && rsv_blocks.back()!=good) + while(blocks.end()!=cur_blocks_end && blocks.back()!=good) { - rsv_blocks.back()->reserve(0); - rsv_blocks.pop_back(); + if(--blocks.end()==cur_blocks_end) + cur_blocks_end = blocks.end(); + blocks.back()->reserve(0); + blocks.pop_back(); } - if(!rsv_blocks.empty() && rsv_blocks.back()!=start) + if(!blocks.back()!=start) // We got some new blocks, so no longer need to yield yielding_to = 0; // Make any sensorless blocks at the beginning immediately current - BlockList::iterator i; - for(i=rsv_blocks.begin(); (i!=rsv_blocks.end() && !(*i)->get_sensor_id()); ++i) ; - if(i!=rsv_blocks.begin()) - cur_blocks.splice(cur_blocks.end(), rsv_blocks, rsv_blocks.begin(), i); + while(cur_blocks_end!=blocks.end() && !(*cur_blocks_end)->get_sensor_id()) + ++cur_blocks_end; if(try_divert && divert(*divert_track)) return reserve_more(); @@ -1063,28 +1049,20 @@ unsigned Train::reserve_more() float Train::get_reserved_distance_until(const Block *until_block, bool back) const { - if(cur_blocks.empty()) + if(blocks.empty()) return 0; Vehicle &veh = *(reverse!=back ? vehicles.back() : vehicles.front()); const VehicleType &vtype = veh.get_type(); TrackIter track(veh.get_track(), veh.get_entry()); - if(!track) + if(!track) // XXX Probably unnecessary return 0; - BlockList::const_iterator block = cur_blocks.begin(); - while(block!=rsv_blocks.end() && !(*block)->has_track(*track)) - { + BlockList::const_iterator block = blocks.begin(); + while(block!=blocks.end() && !(*block)->has_track(*track)) ++block; - if(block==cur_blocks.end()) - { - if(back) - return 0; - block = rsv_blocks.begin(); - } - } - if(block==rsv_blocks.end() || &**block==until_block) + if(block==blocks.end() || &**block==until_block) return 0; float result = veh.get_offset(); @@ -1104,16 +1082,14 @@ float Train::get_reserved_distance_until(const Block *until_block, bool back) co { if(back) { - if(block==cur_blocks.begin()) + if(block==blocks.begin()) break; --block; } else { ++block; - if(block==cur_blocks.end()) - block = rsv_blocks.begin(); - if(block==rsv_blocks.end()) + if(block==blocks.end()) break; } @@ -1203,25 +1179,28 @@ void Train::set_status(const string &s) signal_status_changed.emit(s); } -void Train::release_blocks(BlockList &blocks) +void Train::release_blocks() { - release_blocks(blocks, blocks.begin(), blocks.end()); + release_blocks(blocks.begin(), blocks.end()); } -void Train::release_blocks(BlockList &blocks, BlockList::iterator begin, BlockList::iterator end) +void Train::release_blocks(BlockList::iterator begin, BlockList::iterator end) { while(begin!=end) { + if(begin==cur_blocks_end) + cur_blocks_end = end; + Block &block = **begin; blocks.erase(begin++); block.reserve(0); } } -void Train::reverse_blocks(BlockList &blocks) const +void Train::reverse_blocks(BlockList &blks) const { - blocks.reverse(); - for(BlockList::iterator i=blocks.begin(); i!=blocks.end(); ++i) + blks.reverse(); + for(BlockList::iterator i=blks.begin(); i!=blks.end(); ++i) *i = i->reverse(); } @@ -1250,15 +1229,12 @@ Route *Train::create_lead_route(Route *lead, const Route *target) } set tracks; - for(BlockList::iterator i=cur_blocks.begin(); i!=rsv_blocks.end(); ) + for(BlockList::iterator i=blocks.begin(); i!=blocks.end(); ++i) { const set &btracks = (*i)->get_tracks(); for(set::const_iterator j=btracks.begin(); j!=btracks.end(); ++j) if(!target || !target->has_track(**j)) tracks.insert(*j); - - if(++i==cur_blocks.end()) - i = rsv_blocks.begin(); } lead->add_tracks(tracks); @@ -1349,9 +1325,9 @@ Train::Loader::Loader(Train &t): void Train::Loader::finish() { - if(!obj.cur_blocks.empty()) + if(!obj.blocks.empty()) { - TrackIter track = obj.cur_blocks.front().track_iter(); + TrackIter track = obj.blocks.front().track_iter(); float offset = 2*obj.layout.get_catalogue().get_scale(); obj.vehicles.back()->place(*track, track.entry(), offset, Vehicle::BACK_BUFFER); @@ -1382,7 +1358,7 @@ void Train::Loader::block(unsigned id) entry = 0; blk->reserve(&obj); - obj.cur_blocks.push_back(BlockIter(blk, entry)); + obj.blocks.push_back(BlockIter(blk, entry)); if(blk->get_sensor_id()) obj.layout.get_driver().set_sensor(blk->get_sensor_id(), true); diff --git a/source/libmarklin/train.h b/source/libmarklin/train.h index e55e36e..d637cc0 100644 --- a/source/libmarklin/train.h +++ b/source/libmarklin/train.h @@ -79,8 +79,8 @@ private: int priority; const Train *yielding_to; std::vector vehicles; - BlockList cur_blocks; - BlockList rsv_blocks; + BlockList blocks; + BlockList::iterator cur_blocks_end; Block *pending_block; bool reserving; bool advancing; @@ -141,7 +141,7 @@ public: const Route *get_route() const; void place(Block &, unsigned); void unplace(); - bool is_placed() const { return !cur_blocks.empty(); } + bool is_placed() const { return !blocks.empty(); } bool free_block(Block &); void free_noncritical_blocks(); int get_entry_to_block(Block &) const; @@ -166,8 +166,8 @@ private: unsigned find_speed(float) const; float get_travel_speed() const; void set_status(const std::string &); - void release_blocks(BlockList &); - void release_blocks(BlockList &, BlockList::iterator, BlockList::iterator); + void release_blocks(); + void release_blocks(BlockList::iterator, BlockList::iterator); void reverse_blocks(BlockList &) const; bool advance_route(std::list::iterator &, Track &); Route *create_lead_route(Route *, const Route *);