From 91131237203bffe734219ab8b82b9d17f5d7a87d Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 11 Feb 2015 17:35:56 +0200 Subject: [PATCH] Apply all planned routes at once Letting each router to do it separately in the tick function causes certain problems with synchronization. In particular, sequence points are difficult to synchronize unless the route update is atomic. --- source/libr2c2/trainrouter.cpp | 62 +++++++++++++++++++++++----------- source/libr2c2/trainrouter.h | 3 ++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/source/libr2c2/trainrouter.cpp b/source/libr2c2/trainrouter.cpp index 2d6ab54..27fca7a 100644 --- a/source/libr2c2/trainrouter.cpp +++ b/source/libr2c2/trainrouter.cpp @@ -63,6 +63,24 @@ const Route *TrainRouter::get_route() const return routes.front(); } +void TrainRouter::use_planned_route() +{ + if(!planner || planner->get_result()!=TrainRoutePlanner::COMPLETE) + return; + + const list &planned_routes = planner->get_routes_for(train); + + routes.clear(); + routes.insert(routes.end(), planned_routes.begin(), planned_routes.end()); + create_lead_route(); + + sequence_points = planner->get_sequence_for(train); + current_sequence = 0; + sequence_check_pending = false; + + route_changed(); +} + void TrainRouter::route_changed() { BlockIter fncb = train.get_first_noncritical_block(); @@ -218,24 +236,7 @@ void TrainRouter::tick(const Time::TimeDelta &dt) start_planning(train.get_layout()); if(planner && planner->check()!=TrainRoutePlanner::PENDING) - { - waypoints_changed = false; - if(planner->get_result()==TrainRoutePlanner::COMPLETE) - { - const list &planned_routes = planner->get_routes_for(train); - - routes.clear(); - routes.insert(routes.end(), planned_routes.begin(), planned_routes.end()); - create_lead_route(); - - sequence_points = planner->get_sequence_for(train); - current_sequence = 0; - sequence_check_pending = false; - - route_changed(); - } - planner = 0; - } + apply_plan(train.get_layout(), *planner); if(sequence_check_pending) { @@ -488,14 +489,19 @@ bool TrainRouter::advance_to_track(RouteList::iterator &route, const TrackIter & return true; } -void TrainRouter::start_planning(Layout &layout) +void TrainRouter::get_routers(Layout &layout, vector &routers) { - vector routers; const map &trains = layout.get_trains(); routers.reserve(trains.size()); for(map::const_iterator i=trains.begin(); i!=trains.end(); ++i) if(TrainRouter *router = i->second->get_ai_of_type()) routers.push_back(router); +} + +void TrainRouter::start_planning(Layout &layout) +{ + vector routers; + get_routers(layout, routers); for(vector::const_iterator i=routers.begin(); i!=routers.end(); ++i) if((*i)->metrics_stale) @@ -503,11 +509,27 @@ void TrainRouter::start_planning(Layout &layout) RefPtr planner = new TrainRoutePlanner(layout); for(vector::const_iterator i=routers.begin(); i!=routers.end(); ++i) + { + (*i)->waypoints_changed = false; (*i)->planner = planner; + } planner->plan_async(); } +void TrainRouter::apply_plan(Layout &layout, TrainRoutePlanner &planner) +{ + vector routers; + get_routers(layout, routers); + + for(vector::const_iterator i=routers.begin(); i!=routers.end(); ++i) + if((*i)->planner.get()==&planner) + { + (*i)->use_planned_route(); + (*i)->planner = 0; + } +} + TrainRouter::SequencePoint::SequencePoint(Block &b, unsigned o): block(&b), diff --git a/source/libr2c2/trainrouter.h b/source/libr2c2/trainrouter.h index 80908d5..4571209 100644 --- a/source/libr2c2/trainrouter.h +++ b/source/libr2c2/trainrouter.h @@ -79,6 +79,7 @@ public: const Route *get_route() const; unsigned get_current_sequence() const { return current_sequence; } private: + void use_planned_route(); void route_changed(); public: @@ -108,7 +109,9 @@ private: bool is_valid_for_track(const Route &, const TrackIter &) const; bool advance_to_track(RouteList::iterator &, const TrackIter &); + static void get_routers(Layout &, std::vector &); static void start_planning(Layout &); + static void apply_plan(Layout &, TrainRoutePlanner &); }; } // namespace R2C2 -- 2.43.0