+void BlockAllocator::advance_front(const Block *block, bool inclusive)
+{
+ BlockList::iterator end;
+ if(block)
+ {
+ end = cur_blocks_end;
+ if(inclusive)
+ --end;
+ end = find_if(end, blocks.end(), BlockMatch(*block));
+ if(inclusive && end!=blocks.end())
+ ++end;
+ }
+ else
+ end = blocks.end();
+
+ if(end==blocks.end() && blocks.back().block()==pending_block)
+ --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)
+ signal_advanced.emit(**i, (*i)->get_sensor());
+}
+
+void BlockAllocator::advance_front(const Sensor *sensor)
+{
+ if(sensor)
+ advance_front(sensor->get_block(), dynamic_cast<const BeamGate *>(sensor));
+ else
+ advance_front(0, false);
+}
+
+void BlockAllocator::advance_back()
+{
+ bool rev = train.get_controller().get_reverse();
+ const Vehicle &veh = train.get_vehicle(rev ? 0 : train.get_n_vehicles()-1);
+ const Block &veh_block = veh.get_placement().get_position(rev ? VehiclePlacement::FRONT_AXLE : VehiclePlacement::BACK_AXLE)->get_block();
+
+ bool pending_cleared = false;
+
+ /* Sensors aren't guaranteed to be detriggered in order. Go through the
+ block list and locate the first sensor that's still active. */
+ BlockList::iterator end = blocks.end();
+ for(BlockList::iterator i=blocks.begin(); i!=cur_blocks_end; ++i)
+ {
+ Block *block = &**i;
+ list<Sensor *> sensors;
+
+ /* Collect all sensors from the block in the order they are expected to
+ detrigger. */
+ for(TrackIter j=i->track_iter(); (j && &j->get_block()==block); j=j.next())
+ if(!j->get_attachments().empty())
+ {
+ Track::AttachmentList attachments = j->get_attachments_ordered(j.entry());
+ for(Track::AttachmentList::const_iterator k=attachments.begin(); k!=attachments.end(); ++k)
+ if(BeamGate *gate = dynamic_cast<BeamGate *>(*k))
+ sensors.push_back(gate);
+ }
+
+ if(Sensor *sensor = (*i)->get_sensor())
+ sensors.push_back(sensor);
+
+ /* See if any sensor is still active, and record the position of the
+ last inactive sensor. */
+ bool active_sensor = false;
+ for(list<Sensor *>::const_iterator j=sensors.begin(); (!active_sensor && j!=sensors.end()); ++j)
+ {
+ if((*j)->get_state())
+ active_sensor = true;
+ else
+ end = i;
+ }
+
+ if(block==pending_block)
+ pending_cleared = true;
+
+ // Stop if we encounter an active sensor or the train's last vehicle
+ if(block==&veh_block || active_sensor)
+ {
+ if(end!=blocks.end())
+ {
+ /* If the last inactive sensor was in an earlier block, release
+ that block as well. */
+ if(i!=end)
+ ++end;
+ release_blocks_begin(end);
+ signal_rear_advanced.emit(*last());
+ }
+
+ if(pending_cleared)
+ reserve_more();
+
+ return;
+ }
+ }
+}
+