@@ -9,6 +9,7 @@ All rights reserved (see LICENSE).
99
1010#include < algorithm>
1111#include < mutex>
12+ #include < semaphore>
1213#include < thread>
1314
1415#if USE_LIBOSRM
@@ -1248,16 +1249,44 @@ Solution Input::solve(const unsigned nb_searches,
12481249 .count ();
12491250
12501251 if (_geometry) {
1251- for (auto & route : sol.routes ) {
1252- const auto & profile = route.profile ;
1253- auto rw = std::ranges::find_if (_routing_wrappers, [&](const auto & wr) {
1254- return wr->profile == profile;
1255- });
1256- if (rw == _routing_wrappers.end ()) {
1257- throw InputException (
1258- " Route geometry request with non-routable profile " + profile + " ." );
1252+ std::vector<std::jthread> threads;
1253+ threads.reserve (sol.routes .size ());
1254+ std::exception_ptr ep = nullptr ;
1255+ std::mutex ep_m;
1256+ std::counting_semaphore<MAX_ROUTING_THREADS> semaphore (
1257+ std::min (MAX_ROUTING_THREADS, nb_thread));
1258+
1259+ auto run_routing = [this , &semaphore, &sol, &ep, &ep_m](std::size_t i) {
1260+ semaphore.acquire ();
1261+ try {
1262+ auto & route = sol.routes [i];
1263+ const auto & profile = route.profile ;
1264+ auto rw = std::ranges::find_if (_routing_wrappers, [&](const auto & wr) {
1265+ return wr->profile == profile;
1266+ });
1267+ if (rw == _routing_wrappers.end ()) {
1268+ throw InputException (
1269+ " Route geometry request with non-routable profile " + profile +
1270+ " ." );
1271+ }
1272+ (*rw)->add_geometry (route);
1273+ } catch (...) {
1274+ const std::scoped_lock<std::mutex> lock (ep_m);
1275+ ep = std::current_exception ();
12591276 }
1260- (*rw)->add_geometry (route);
1277+ semaphore.release ();
1278+ };
1279+
1280+ for (std::size_t i = 0 ; i < sol.routes .size (); ++i) {
1281+ threads.emplace_back (run_routing, i);
1282+ }
1283+
1284+ for (auto & t : threads) {
1285+ t.join ();
1286+ }
1287+
1288+ if (ep != nullptr ) {
1289+ std::rethrow_exception (ep);
12611290 }
12621291
12631292 _end_routing = std::chrono::high_resolution_clock::now ();
0 commit comments