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.
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));
{
release_blocks_end(cur_blocks_end);
pending_block = 0;
+ reserve_pending = false;
}
}
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())
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)
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");
const Block *stop_at_block;
bool reserving;
bool advancing;
+ bool reserve_pending;
public:
BlockAllocator(Train &);
bool has_block(const Block &) const;
bool is_block_current(const Block &) const;
+ void tick();
+
private:
void reserve_more();
bool reserve_block(const BlockIter &);
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);
}
{
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);
}
}
-void Layout::block_reserved(Block &block, Train *train)
-{
- if(emitting_block_reserved)
- {
- if(!train)
- {
- for(deque<BlockReservation>::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<typename B>
Layout::Storage<B>::~Storage()
}
-Layout::BlockReservation::BlockReservation(Block &b, Train *t):
- block(&b),
- train(t)
-{ }
-
-
Layout::Loader::Loader(Layout &l):
DataFile::ObjectLoader<Layout>(l)
{
void del();
};
- struct BlockReservation
- {
- Block *block;
- Train *train;
-
- BlockReservation(Block &, Train *);
- };
-
public:
typedef std::vector<Zone *> ZoneArray;
std::map<unsigned, Train *> trains;
Msp::Time::TimeStamp last_tick;
unsigned next_turnout_addr;
- bool emitting_block_reserved;
- std::deque<BlockReservation> block_reserve_queue;
public:
Layout(Catalogue &, Driver * = 0);
void save_dynamic(const std::string &) const;
private:
void sensor_state_changed(Sensor &, Sensor::State);
- void block_reserved(Block &, Train *);
};
} // namespace R2C2
Driver &driver = layout.get_driver();
+ allocator.tick();
+
bool intent_to_move = false;
for(list<TrainAI *>::iterator i=ais.begin(); i!=ais.end(); ++i)
{