From edaa452a8bd98b052f3a2ecbf76252b43e08e2f7 Mon Sep 17 00:00:00 2001 From: Hirek Date: Wed, 17 Sep 2025 00:38:28 +0200 Subject: [PATCH] Experimental async train processing option --- Globals.cpp | 5 +++++ Globals.h | 1 + Train.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ Train.h | 1 + application.cpp | 2 +- drivermode.cpp | 11 ++++++++++- 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Globals.cpp b/Globals.cpp index 28325384..b36aab46 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -59,6 +59,11 @@ global_settings::ConfigParse(cParser &Parser) { Parser.getTokens(); Parser >> local_start_vehicle; } + else if (token == "async.trains") + { + Parser.getTokens(); + Parser >> trainAsyncProcessing; + } else if (token == "fieldofview") { Parser.getTokens(1, false); diff --git a/Globals.h b/Globals.h index 106f01ca..8852a2f3 100644 --- a/Globals.h +++ b/Globals.h @@ -52,6 +52,7 @@ struct global_settings { int iSlowMotion{ 0 }; // info o malym FPS: 0-OK, 1-wyłączyć multisampling, 3-promień 1.5km, 7-1km basic_light DayLight; float SunAngle{ 0.f }; // angle of the sun relative to horizon + bool trainAsyncProcessing{false}; double fLuminance{ 1.0 }; // jasność światła do automatycznego zapalania double fTimeAngleDeg{ 0.0 }; // godzina w postaci kąta float fClockAngleDeg[ 6 ]; // kąty obrotu cylindrów dla zegara cyfrowego diff --git a/Train.cpp b/Train.cpp index f639df31..f0a3c255 100644 --- a/Train.cpp +++ b/Train.cpp @@ -31,6 +31,7 @@ http://mozilla.org/MPL/2.0/. #include "Console.h" #include "application.h" #include "renderer.h" +#include /* namespace input { @@ -11100,6 +11101,46 @@ uint16_t TTrain::id() { return vid; } +void train_table::updateAsync(double dt) +{ + // init random engine + std::vector>> futures; + futures.reserve(m_items.size()); + + // update all trains in paallel + for (TTrain *train : m_items) + { + if (!train) + continue; + + futures.emplace_back(train, std::async(std::launch::async, [train, dt]() { train->Update(dt); })); + } + + // wait for every train to finish processing + for (auto &pair : futures) + { + pair.second.get(); + } + + // perform deletions + for (TTrain *train : m_items) + { + if (!train) + continue; + + if (train->pending_delete) + { + purge(train->Dynamic()->name()); + if (simulation::Train == train) + simulation::Train = nullptr; + } + else if (simulation::Train != train && Global.network_servers.empty() && !Global.network_client) + { + purge(train->Dynamic()->name()); + } + } +} + void train_table::update(double dt) { for (TTrain *train : m_items) { diff --git a/Train.h b/Train.h index 1aa2d0cf..47c21866 100644 --- a/Train.h +++ b/Train.h @@ -929,6 +929,7 @@ private: class train_table : public basic_table { public: void update( double dt ); + void updateAsync( double dt ); TTrain *find_id( std::uint16_t const Id ) const; }; diff --git a/application.cpp b/application.cpp index 83b88b92..83d2f463 100644 --- a/application.cpp +++ b/application.cpp @@ -497,7 +497,7 @@ eu07_application::run() { // send commands to command queue simulation::Commands.push_commands(commands_to_exec); - // do actual frame processing + // do actual frame processing (depending on mode) if (!m_modes[ m_modestack.top() ]->update()) return 0; diff --git a/drivermode.cpp b/drivermode.cpp index 3e780bc9..6652c384 100644 --- a/drivermode.cpp +++ b/drivermode.cpp @@ -274,7 +274,16 @@ driver_mode::update() { else TSubModel::iInstance = 0; - simulation::Trains.update(deltatime); + + if (Global.trainAsyncProcessing) + { + simulation::Trains.updateAsync(deltatime); + } + else + { + simulation::Trains.update(deltatime); + } + simulation::Events.update(); simulation::Region->update_events(); simulation::Lights.update();