+TrainRoutePlanner::~TrainRoutePlanner()
+{
+ if(thread)
+ {
+ thread->join();
+ delete thread;
+ }
+}
+
+TrainRoutePlanner::Result TrainRoutePlanner::plan()
+{
+ prepare_plan();
+ create_plan();
+ if(result==PENDING)
+ finalize_plan();
+
+ return result;
+}
+
+void TrainRoutePlanner::plan_async()
+{
+ if(thread)
+ throw logic_error("already planning");
+
+ prepare_plan();
+ thread = new PlanningThread(*this);
+}
+
+TrainRoutePlanner::Result TrainRoutePlanner::check()
+{
+ if(result==PENDING && goal)
+ {
+ if(thread)
+ {
+ thread->join();
+ delete thread;
+ thread = 0;
+ }
+ finalize_plan();
+ }
+
+ return result;
+}
+
+const list<Route *> &TrainRoutePlanner::get_routes_for(const Train &train) const
+{
+ return get_train_info(train).routes;
+}
+
+const list<TrainRouter::SequencePoint> &TrainRoutePlanner::get_sequence_for(const Train &train) const
+{
+ return get_train_info(train).sequence;
+}
+
+const TrainRoutePlanner::TrainRoutingInfo &TrainRoutePlanner::get_train_info(const Train &train) const
+{
+ for(vector<TrainRoutingInfo>::const_iterator i=routed_trains.begin(); i!=routed_trains.end(); ++i)
+ if(i->train==&train)
+ return *i;
+
+ throw key_error(train.get_name());
+}
+
+const TrainRoutePlanner::RoutingStep &TrainRoutePlanner::get_step()
+{
+ steps.splice(steps.end(), queue, queue.begin());
+ return steps.back();
+}
+
+void TrainRoutePlanner::prepare_plan()