From d0881a98a6240758ac1aeceaa9443d718ab1ad5c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 8 Apr 2015 19:55:21 +0300 Subject: [PATCH] Avoid nested block reservations completely The emission queue turned out to still be broken in some situations. Rather than make the logic even more complex, I'll just delay the reservation until we're no longer inside a signal emission. For good measure, the same is applied to turnout and sensor signals too. --- source/libr2c2/blockallocator.cpp | 19 +++++++++++---- source/libr2c2/blockallocator.h | 3 +++ source/libr2c2/layout.cpp | 40 ++----------------------------- source/libr2c2/layout.h | 11 --------- source/libr2c2/train.cpp | 2 ++ 5 files changed, 22 insertions(+), 53 deletions(-) diff --git a/source/libr2c2/blockallocator.cpp b/source/libr2c2/blockallocator.cpp index 7cca79f..cb6b912 100644 --- a/source/libr2c2/blockallocator.cpp +++ b/source/libr2c2/blockallocator.cpp @@ -34,7 +34,8 @@ BlockAllocator::BlockAllocator(Train &t): pending_block(0), stop_at_block(0), reserving(false), - advancing(false) + advancing(false), + reserve_pending(false) { Layout &layout = train.get_layout(); layout.signal_block_reserved.connect(sigc::mem_fun(this, &BlockAllocator::block_reserved)); @@ -59,6 +60,7 @@ void BlockAllocator::set_active(bool a) { release_blocks_end(cur_blocks_end); pending_block = 0; + reserve_pending = false; } } @@ -186,6 +188,15 @@ bool BlockAllocator::is_block_current(const Block &block) const return find_if(blocks.begin(), end, BlockMatch(block))!=cur_blocks_end; } +void BlockAllocator::tick() +{ + if(reserve_pending) + { + reserve_pending = false; + reserve_more(); + } +} + void BlockAllocator::reserve_more() { if(blocks.empty()) @@ -483,13 +494,13 @@ void BlockAllocator::turnout_path_changing(Track &track) void BlockAllocator::turnout_path_changed(Track &track) { if(&track.get_block()==pending_block && !reserving) - reserve_more(); + reserve_pending = true; } void BlockAllocator::block_reserved(Block &block, const Train *tr) { if(&block==pending_block && !tr && !reserving) - reserve_more(); + reserve_pending = true; } void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) @@ -508,7 +519,7 @@ void BlockAllocator::sensor_state_changed(Sensor &sensor, Sensor::State state) advance_front(next_sensor); if(active) - reserve_more(); + reserve_pending = true; } else if(!is_block_current(*block)) train.get_layout().emergency(block, "Sensor for "+train.get_name()+" triggered out of order"); diff --git a/source/libr2c2/blockallocator.h b/source/libr2c2/blockallocator.h index 2e3f3b2..b401233 100644 --- a/source/libr2c2/blockallocator.h +++ b/source/libr2c2/blockallocator.h @@ -44,6 +44,7 @@ private: const Block *stop_at_block; bool reserving; bool advancing; + bool reserve_pending; public: BlockAllocator(Train &); @@ -65,6 +66,8 @@ public: bool has_block(const Block &) const; bool is_block_current(const Block &) const; + void tick(); + private: void reserve_more(); bool reserve_block(const BlockIter &); diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index bc149df..dc07c19 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -41,8 +41,7 @@ namespace R2C2 { Layout::Layout(Catalogue &c, Driver *d): catalogue(c), driver(d), - next_turnout_addr(0x800), - emitting_block_reserved(false) + next_turnout_addr(0x800) { clock.set_rate(60); } @@ -123,7 +122,7 @@ void Layout::add(Block &b) { if(track_chains.insert(b)) { - sigc::connection conn = b.signal_reserved.connect(sigc::bind<0>(sigc::mem_fun(this, &Layout::block_reserved), sigc::ref(b))); + sigc::connection conn = b.signal_reserved.connect(sigc::bind<0>(signal_block_reserved, sigc::ref(b))); try { signal_track_chain_added.emit(b); @@ -562,35 +561,6 @@ void Layout::sensor_state_changed(Sensor &sensor, Sensor::State state) } } -void Layout::block_reserved(Block &block, Train *train) -{ - if(emitting_block_reserved) - { - if(!train) - { - for(deque::iterator i=block_reserve_queue.end(); i!=block_reserve_queue.begin(); ) - if((--i)->block==&block) - { - block_reserve_queue.erase(i); - return; - } - } - - block_reserve_queue.push_back(BlockReservation(block, train)); - } - else - { - SetFlag setf(emitting_block_reserved); - signal_block_reserved.emit(block, train); - while(!block_reserve_queue.empty()) - { - BlockReservation br = block_reserve_queue.front(); - block_reserve_queue.pop_front(); - signal_block_reserved.emit(*br.block, br.train); - } - } -} - template Layout::Storage::~Storage() @@ -645,12 +615,6 @@ void Layout::Storage::del() } -Layout::BlockReservation::BlockReservation(Block &b, Train *t): - block(&b), - train(t) -{ } - - Layout::Loader::Loader(Layout &l): DataFile::ObjectLoader(l) { diff --git a/source/libr2c2/layout.h b/source/libr2c2/layout.h index e06d4fb..2211de0 100644 --- a/source/libr2c2/layout.h +++ b/source/libr2c2/layout.h @@ -70,14 +70,6 @@ private: void del(); }; - struct BlockReservation - { - Block *block; - Train *train; - - BlockReservation(Block &, Train *); - }; - public: typedef std::vector ZoneArray; @@ -102,8 +94,6 @@ private: std::map trains; Msp::Time::TimeStamp last_tick; unsigned next_turnout_addr; - bool emitting_block_reserved; - std::deque block_reserve_queue; public: Layout(Catalogue &, Driver * = 0); @@ -161,7 +151,6 @@ public: void save_dynamic(const std::string &) const; private: void sensor_state_changed(Sensor &, Sensor::State); - void block_reserved(Block &, Train *); }; } // namespace R2C2 diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 4372377..889f21e 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -327,6 +327,8 @@ void Train::tick(const Time::TimeDelta &dt) Driver &driver = layout.get_driver(); + allocator.tick(); + bool intent_to_move = false; for(list::iterator i=ais.begin(); i!=ais.end(); ++i) { -- 2.43.0