Thread testTrackClearances
We are frequently testing thousands of track segments. They can each be uniquely tested in parallel with reporting and marking guarded by mutexes. This speeds up the DRC tests substantially Fixes https://gitlab.com/kicad/code/kicad/-/issues/15466
This commit is contained in:
parent
b2ef620ea6
commit
f4afd7e363
|
@ -75,6 +75,7 @@ const wxString DRC_TEST_PROVIDER::GetDescription() const { return wxEmptyString;
|
|||
void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
|
||||
const VECTOR2I& aMarkerPos, int aMarkerLayer )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( m_statsMutex );
|
||||
if( item->GetViolatingRule() )
|
||||
accountCheck( item->GetViolatingRule() );
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ protected:
|
|||
DRC_ENGINE* m_drcEngine;
|
||||
std::unordered_map<const DRC_RULE*, int> m_stats;
|
||||
bool m_isRuleDriven = true;
|
||||
std::mutex m_statsMutex;
|
||||
};
|
||||
|
||||
#endif // DRC_TEST_PROVIDER__H
|
||||
|
|
|
@ -559,19 +559,22 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
{
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int progressDelta = 100;
|
||||
int ii = 0;
|
||||
|
||||
reportAux( wxT( "Testing %d tracks & vias..." ), m_board->Tracks().size() );
|
||||
|
||||
std::map<BOARD_ITEM*, int> freePadsUsageMap;
|
||||
std::unordered_map<PTR_PTR_CACHE_KEY, layers_checked> checkedPairs;
|
||||
std::mutex checkedPairsMutex;
|
||||
std::mutex freePadsUsageMapMutex;
|
||||
std::atomic<int> tracks_checked( 0 );
|
||||
|
||||
LSET boardCopperLayers = LSET::AllCuMask( m_board->GetCopperLayerCount() );
|
||||
|
||||
for( PCB_TRACK* track : m_board->Tracks() )
|
||||
auto testTrack = [&]( const int start_idx, const int end_idx )
|
||||
{
|
||||
if( !reportProgress( ii++, m_board->Tracks().size(), progressDelta ) )
|
||||
break;
|
||||
for( int trackIdx = start_idx; trackIdx < end_idx; ++trackIdx )
|
||||
{
|
||||
PCB_TRACK* track = m_board->Tracks()[trackIdx];
|
||||
|
||||
for( PCB_LAYER_ID layer : LSET( track->GetLayerSet() & boardCopperLayers ).Seq() )
|
||||
{
|
||||
|
@ -594,6 +597,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
|
||||
std::swap( a, b );
|
||||
|
||||
std::lock_guard<std::mutex> lock( checkedPairsMutex );
|
||||
auto it = checkedPairs.find( { a, b } );
|
||||
|
||||
if( it != checkedPairs.end() && ( it->second.layers.test( layer )
|
||||
|
@ -614,6 +618,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
{
|
||||
if( other->GetEffectiveShape( layer )->Collide( trackShape.get() ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( freePadsUsageMapMutex );
|
||||
auto it = freePadsUsageMap.find( other );
|
||||
|
||||
if( it == freePadsUsageMap.end() )
|
||||
|
@ -636,13 +641,14 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
if( static_cast<void*>( a ) > static_cast<void*>( b ) )
|
||||
std::swap( a, b );
|
||||
|
||||
auto it = checkedPairs.find( { a, b } );
|
||||
|
||||
// If we get an error, mark the pair as having a clearance error already
|
||||
// Only continue if we are reporting all track errors
|
||||
if( !testSingleLayerItemAgainstItem( track, trackShape.get(), layer,
|
||||
other ) )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( checkedPairsMutex );
|
||||
auto it = checkedPairs.find( { a, b } );
|
||||
|
||||
if( it != checkedPairs.end() )
|
||||
it->second.has_error = true;
|
||||
|
||||
|
@ -661,6 +667,24 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++tracks_checked;
|
||||
}
|
||||
};
|
||||
|
||||
thread_pool& tp = GetKiCadThreadPool();
|
||||
|
||||
tp.push_loop( m_board->Tracks().size(), testTrack );
|
||||
|
||||
while( tracks_checked < static_cast<int>( m_board->Tracks().size() ) )
|
||||
{
|
||||
if( !reportProgress( tracks_checked, m_board->Tracks().size(), progressDelta ) )
|
||||
{
|
||||
tp.wait_for_tasks();
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue