From 1066595a2c51296abc0bab75f2ee3a617e12be37 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 15 Jul 2025 14:52:37 -0700 Subject: [PATCH] Add wallclock timeout to PNS walkaround WALKAROUND::singlestep is used by both shove and walkaround modes and can bog down when applied to clusters with many objects. In these cases, we are unlikely to find a viable solution and it is beter to allow the user to find a different ending position (cherry picked from commit d9cfb942812a57238d5ed6bbaa2c1d22a8676071) --- common/advanced_config.cpp | 6 ++++++ include/advanced_config.h | 9 +++++++++ pcbnew/router/pns_walkaround.cpp | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index 99435ca90d..50e304d307 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -128,6 +128,7 @@ static const wxChar ExcludeFromSimulationLineWidth[] = wxT( "ExcludeFromSimulati static const wxChar GitIconRefreshInterval[] = wxT( "GitIconRefreshInterval" ); static const wxChar ConfigurableToolbars[] = wxT( "ConfigurableToolbars" ); static const wxChar MaxPastedTextLength[] = wxT( "MaxPastedTextLength" ); +static const wxChar PNSProcessClusterTimeout[] = wxT( "PNSProcessClusterTimeout" ); } // namespace KEYS @@ -312,6 +313,8 @@ ADVANCED_CFG::ADVANCED_CFG() m_MaxPastedTextLength = 100; + m_PNSProcessClusterTimeout = 100; // Default: 100 ms + loadFromConfigFile(); } @@ -602,6 +605,9 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) &m_MaxPastedTextLength, m_MaxPastedTextLength, 0, 100000 ) ); + configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::PNSProcessClusterTimeout, + &m_PNSProcessClusterTimeout, 100, 10, 10000 ) ); + // Special case for trace mask setting...we just grab them and set them immediately // Because we even use wxLogTrace inside of advanced config wxString traceMasks; diff --git a/include/advanced_config.h b/include/advanced_config.h index e8aae7e75c..fa80c046bd 100644 --- a/include/advanced_config.h +++ b/include/advanced_config.h @@ -757,6 +757,15 @@ public: */ int m_MaxPastedTextLength; + /** + * Timeout for the PNS router's processCluster wallclock timeout, in milliseconds. + * + * Setting name: "PNSProcessClusterTimeoutMs" + * Valid values: 10 to 10000 + * Default value: 100 + */ + int m_PNSProcessClusterTimeout; + ///@} private: diff --git a/pcbnew/router/pns_walkaround.cpp b/pcbnew/router/pns_walkaround.cpp index ecf000b218..3ed4ae9038 100644 --- a/pcbnew/router/pns_walkaround.cpp +++ b/pcbnew/router/pns_walkaround.cpp @@ -19,6 +19,8 @@ * with this program. If not, see . */ +#include +#include #include #include @@ -138,10 +140,29 @@ bool WALKAROUND::singleStep() auto processCluster = [ & ] ( TOPOLOGY::CLUSTER& aCluster, LINE& aLine, bool aCw ) -> bool { + using namespace std::chrono; + auto start_time = steady_clock::now(); + + int timeout_ms = ADVANCED_CFG::GetCfg().m_PNSProcessClusterTimeout; + PNS_DBG( Dbg(), BeginGroup, wxString::Format( "cluster-details [cw %d]", aCw?1:0 ), 1 ); for( auto& clItem : aCluster.m_items ) { + // Check for wallclock timeout + // Emprically, 100ms seems to be about where you're not going to find a valid path + // if you haven't found it by then. This allows the user to adjust their mouse position + // to get a better path without waiting too long. + auto now = steady_clock::now(); + auto elapsed = duration_cast( now - start_time ).count(); + + if( elapsed > timeout_ms ) + { + PNS_DBG( Dbg(), Message, wxString::Format( "processCluster timeout after %d ms", timeout_ms ) ); + PNS_DBGN( Dbg(), EndGroup ); + return false; + } + int clearance = m_world->GetClearance( clItem, &aLine, false ); SHAPE_LINE_CHAIN hull = clItem->Hull( clearance + 1000, aLine.Width(), aLine.Layer() );