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
This commit is contained in:
Jeff Young 2024-01-03 12:42:54 +00:00
parent c8c0685ff2
commit 8993cd12a6
1 changed files with 26 additions and 16 deletions

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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; int& largestPhysicalClearance = m_board->m_DRCMaxPhysicalClearance;
DRC_CONSTRAINT worstConstraint; DRC_CONSTRAINT worstConstraint;
LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() ); LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
thread_pool& tp = GetKiCadThreadPool();
largestClearance = std::max( largestClearance, m_board->GetMaxClearanceValue() ); 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. size_t count = 0;
// Note that zones are -not- done here, so it's reasonably fast. std::atomic<size_t> done( 1 );
size_t progressDelta = 500;
size_t count = 0;
size_t ii = 0;
auto countItems = auto countItems =
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
@ -97,7 +96,7 @@ bool DRC_CACHE_GENERATOR::Run()
auto addToCopperTree = auto addToCopperTree =
[&]( BOARD_ITEM* item ) -> bool [&]( BOARD_ITEM* item ) -> bool
{ {
if( !reportProgress( ii++, count, progressDelta ) ) if( m_drcEngine->IsCancelled() )
return false; return false;
LSET copperLayers = item->GetLayerSet() & boardCopperLayers; LSET copperLayers = item->GetLayerSet() & boardCopperLayers;
@ -117,6 +116,7 @@ bool DRC_CACHE_GENERATOR::Run()
m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance ); m_board->m_CopperItemRTreeCache->Insert( item, layer, largestClearance );
} }
done.fetch_add( 1 );
return true; return true;
}; };
@ -133,13 +133,23 @@ bool DRC_CACHE_GENERATOR::Run()
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems ); forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
std::future<void> retn = tp.submit(
[&]()
{
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
if( !m_board->m_CopperItemRTreeCache )
m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
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<std::mutex> cacheLock( m_board->m_CachesMutex ); m_drcEngine->ReportProgress( static_cast<double>( done ) / count );
status = retn.wait_for( std::chrono::milliseconds( 250 ) );
if( !m_board->m_CopperItemRTreeCache )
m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
} }
if( !reportPhase( _( "Tessellating copper zones..." ) ) ) if( !reportPhase( _( "Tessellating copper zones..." ) ) )
@ -151,9 +161,7 @@ bool DRC_CACHE_GENERATOR::Run()
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
footprint->BuildCourtyardCaches(); footprint->BuildCourtyardCaches();
thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<size_t>> returns; std::vector<std::future<size_t>> returns;
std::atomic<size_t> done( 1 );
returns.reserve( allZones.size() ); returns.reserve( allZones.size() );
@ -188,9 +196,11 @@ bool DRC_CACHE_GENERATOR::Run()
for( ZONE* zone : allZones ) for( ZONE* zone : allZones )
returns.emplace_back( tp.submit( cache_zones, zone ) ); returns.emplace_back( tp.submit( cache_zones, zone ) );
done.store( 1 );
for( const std::future<size_t>& ret : returns ) for( const std::future<size_t>& 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 ) while( status != std::future_status::ready )
{ {