From 8993cd12a6ae6c703fce7f2951ea0b03e8668ffd Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 3 Jan 2024 12:42:54 +0000 Subject: [PATCH] Thread cache generator. This allows us to poll the event loop & update the progress on a time interval rather than on an items-completed interval (the later of which can't easily take host machine performance into account). Fixes https://gitlab.com/kicad/code/kicad/-/issues/16506 --- pcbnew/drc/drc_cache_generator.cpp | 42 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/pcbnew/drc/drc_cache_generator.cpp b/pcbnew/drc/drc_cache_generator.cpp index 9a0e1e8224..a00625b3dc 100644 --- a/pcbnew/drc/drc_cache_generator.cpp +++ b/pcbnew/drc/drc_cache_generator.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2022 KiCad Developers. + * Copyright (C) 2022-2024 KiCad Developers. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -39,6 +39,8 @@ bool DRC_CACHE_GENERATOR::Run() int& largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance; DRC_CONSTRAINT worstConstraint; LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() ); + thread_pool& tp = GetKiCadThreadPool(); + largestClearance = std::max( largestClearance, m_board->GetMaxClearanceValue() ); @@ -81,11 +83,8 @@ bool DRC_CACHE_GENERATOR::Run() } } - // This is the number of tests between 2 calls to the progress bar. - // Note that zones are -not- done here, so it's reasonably fast. - size_t progressDelta = 500; - size_t count = 0; - size_t ii = 0; + size_t count = 0; + std::atomic done( 1 ); auto countItems = [&]( BOARD_ITEM* item ) -> bool @@ -97,7 +96,7 @@ bool DRC_CACHE_GENERATOR::Run() auto addToCopperTree = [&]( BOARD_ITEM* item ) -> bool { - if( !reportProgress( ii++, count, progressDelta ) ) + if( m_drcEngine->IsCancelled() ) return false; LSET copperLayers = item->GetLayerSet() & boardCopperLayers; @@ -117,6 +116,7 @@ bool DRC_CACHE_GENERATOR::Run() m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance ); } + done.fetch_add( 1 ); return true; }; @@ -133,13 +133,23 @@ bool DRC_CACHE_GENERATOR::Run() forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems ); + std::future retn = tp.submit( + [&]() + { + std::unique_lock cacheLock( m_board->m_CachesMutex ); + + if( !m_board->m_CopperItemRTreeCache ) + m_board->m_CopperItemRTreeCache = std::make_shared(); + + forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree ); + } ); + + std::future_status status = retn.wait_for( std::chrono::milliseconds( 250 ) ); + + while( status != std::future_status::ready ) { - std::unique_lock cacheLock( m_board->m_CachesMutex ); - - if( !m_board->m_CopperItemRTreeCache ) - m_board->m_CopperItemRTreeCache = std::make_shared(); - - forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree ); + m_drcEngine->ReportProgress( static_cast( done ) / count ); + status = retn.wait_for( std::chrono::milliseconds( 250 ) ); } if( !reportPhase( _( "Tessellating copper zones..." ) ) ) @@ -151,9 +161,7 @@ bool DRC_CACHE_GENERATOR::Run() for( FOOTPRINT* footprint : m_board->Footprints() ) footprint->BuildCourtyardCaches(); - thread_pool& tp = GetKiCadThreadPool(); std::vector> returns; - std::atomic done( 1 ); returns.reserve( allZones.size() ); @@ -188,9 +196,11 @@ bool DRC_CACHE_GENERATOR::Run() for( ZONE* zone : allZones ) returns.emplace_back( tp.submit( cache_zones, zone ) ); + done.store( 1 ); + for( const std::future& ret : returns ) { - std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) ); + status = ret.wait_for( std::chrono::milliseconds( 250 ) ); while( status != std::future_status::ready ) {