pcbnew: Shift zone filler to std::async
This commit is contained in:
parent
a24bd9baa1
commit
1f25fcd3d6
|
@ -26,6 +26,8 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
#include <class_zone.h>
|
#include <class_zone.h>
|
||||||
|
@ -109,47 +111,66 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones, bool aCheck )
|
||||||
m_progressReporter->SetMaxProgress( toFill.size() );
|
m_progressReporter->SetMaxProgress( toFill.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove deprecaded segment zones (only found in very old boards)
|
||||||
|
m_board->m_SegZoneDeprecated.DeleteAll();
|
||||||
|
|
||||||
std::atomic<size_t> nextItem( 0 );
|
std::atomic<size_t> nextItem( 0 );
|
||||||
std::atomic<size_t> threadsFinished( 0 );
|
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(), toFill.size() );
|
||||||
size_t parallelThreadCount = std::min<size_t>(
|
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
||||||
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
|
|
||||||
toFill.size() );
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
|
||||||
{
|
{
|
||||||
std::thread t = std::thread( [ & ]()
|
size_t num = 0;
|
||||||
|
|
||||||
|
for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
|
||||||
{
|
{
|
||||||
for( size_t i = nextItem.fetch_add( 1 );
|
ZONE_CONTAINER* zone = toFill[i].m_zone;
|
||||||
i < toFill.size();
|
|
||||||
i = nextItem.fetch_add( 1 ) )
|
if( zone->GetFillMode() == ZFM_SEGMENTS )
|
||||||
|
{
|
||||||
|
ZONE_SEGMENT_FILL segFill;
|
||||||
|
fillZoneWithSegments( zone, zone->GetFilledPolysList(), segFill );
|
||||||
|
zone->SetFillSegments( segFill );
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET rawPolys, finalPolys;
|
SHAPE_POLY_SET rawPolys, finalPolys;
|
||||||
ZONE_CONTAINER* zone = toFill[i].m_zone;
|
|
||||||
fillSingleZone( zone, rawPolys, finalPolys );
|
fillSingleZone( zone, rawPolys, finalPolys );
|
||||||
|
|
||||||
zone->SetRawPolysList( rawPolys );
|
zone->SetRawPolysList( rawPolys );
|
||||||
zone->SetFilledPolysList( finalPolys );
|
zone->SetFilledPolysList( finalPolys );
|
||||||
zone->SetIsFilled( true );
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
m_progressReporter->AdvanceProgress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
threadsFinished++;
|
zone->SetIsFilled( true );
|
||||||
} );
|
|
||||||
|
|
||||||
t.detach();
|
if( m_progressReporter )
|
||||||
}
|
m_progressReporter->AdvanceProgress();
|
||||||
|
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
// Finalize the triangulation threads
|
return num;
|
||||||
while( threadsFinished < parallelThreadCount )
|
};
|
||||||
|
|
||||||
|
if( parallelThreadCount <= 1 )
|
||||||
|
fill_lambda( m_progressReporter );
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if( m_progressReporter )
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
m_progressReporter->KeepRefreshing();
|
returns[ii] = std::async( std::launch::async, fill_lambda, m_progressReporter );
|
||||||
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
|
{
|
||||||
|
// Here we balance returns with a 100ms timeout to allow UI updating
|
||||||
|
std::future_status status;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( m_progressReporter )
|
||||||
|
m_progressReporter->KeepRefreshing();
|
||||||
|
|
||||||
|
status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
|
||||||
|
} while( status != std::future_status::ready );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now update the connectivity to check for copper islands
|
// Now update the connectivity to check for copper islands
|
||||||
|
@ -164,13 +185,6 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones, bool aCheck )
|
||||||
connectivity->FindIsolatedCopperIslands( toFill );
|
connectivity->FindIsolatedCopperIslands( toFill );
|
||||||
|
|
||||||
// Now remove insulated copper islands
|
// Now remove insulated copper islands
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->AdvancePhase();
|
|
||||||
m_progressReporter->SetMaxProgress( toFill.size() );
|
|
||||||
m_progressReporter->KeepRefreshing();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool outOfDate = false;
|
bool outOfDate = false;
|
||||||
|
|
||||||
for( auto& zone : toFill )
|
for( auto& zone : toFill )
|
||||||
|
@ -187,12 +201,6 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones, bool aCheck )
|
||||||
|
|
||||||
if( aCheck && zone.m_lastPolys.GetHash() != poly.GetHash() )
|
if( aCheck && zone.m_lastPolys.GetHash() != poly.GetHash() )
|
||||||
outOfDate = true;
|
outOfDate = true;
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->AdvanceProgress();
|
|
||||||
m_progressReporter->KeepRefreshing();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aCheck )
|
if( aCheck )
|
||||||
|
@ -235,99 +243,44 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*> aZones, bool aCheck )
|
||||||
|
|
||||||
|
|
||||||
nextItem = 0;
|
nextItem = 0;
|
||||||
threadsFinished = 0;
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
auto tri_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
|
||||||
{
|
{
|
||||||
std::thread t = std::thread( [ & ]()
|
size_t num = 0;
|
||||||
|
|
||||||
|
for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
|
||||||
{
|
{
|
||||||
for( size_t i = nextItem.fetch_add( 1 );
|
toFill[i].m_zone->CacheTriangulation();
|
||||||
i < toFill.size();
|
num++;
|
||||||
i = nextItem.fetch_add( 1 ) )
|
|
||||||
{
|
|
||||||
toFill[i].m_zone->CacheTriangulation();
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
if( m_progressReporter )
|
||||||
m_progressReporter->AdvanceProgress();
|
m_progressReporter->AdvanceProgress();
|
||||||
}
|
|
||||||
|
|
||||||
threadsFinished++;
|
|
||||||
} );
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Finalize the triangulation threads
|
|
||||||
while( threadsFinished < parallelThreadCount )
|
|
||||||
{
|
|
||||||
if( m_progressReporter )
|
|
||||||
m_progressReporter->KeepRefreshing();
|
|
||||||
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Remove deprecaded segment zones (only found in very old boards)
|
|
||||||
m_board->m_SegZoneDeprecated.DeleteAll();
|
|
||||||
|
|
||||||
// If some zones must be filled by segments, create the filling segments
|
|
||||||
// (note, this is a outdated option, but it exists)
|
|
||||||
int zone_count = std::count_if( toFill.begin(), toFill.end(),
|
|
||||||
[]( CN_ZONE_ISOLATED_ISLAND_LIST& aList )
|
|
||||||
{ return aList.m_zone->GetFillMode() == ZFM_SEGMENTS; } );
|
|
||||||
|
|
||||||
if( zone_count > 0 )
|
|
||||||
{
|
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->AdvancePhase();
|
|
||||||
m_progressReporter->Report( _( "Performing segment fills..." ) );
|
|
||||||
m_progressReporter->SetMaxProgress( zone_count );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parallelThreadCount = std::min<size_t>( static_cast<size_t>( zone_count ), parallelThreadCount );
|
return num;
|
||||||
nextItem = 0;
|
};
|
||||||
threadsFinished = 0;
|
|
||||||
|
if( parallelThreadCount <= 1 )
|
||||||
|
tri_lambda( m_progressReporter );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
|
returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
|
||||||
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
{
|
{
|
||||||
std::thread t = std::thread( [ & ]()
|
// Here we balance returns with a 100ms timeout to allow UI updating
|
||||||
|
std::future_status status;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
for( size_t i = nextItem.fetch_add( 1 );
|
if( m_progressReporter )
|
||||||
i < toFill.size();
|
m_progressReporter->KeepRefreshing();
|
||||||
i = nextItem.fetch_add( 1 ) )
|
|
||||||
{
|
|
||||||
ZONE_CONTAINER* zone = toFill[i].m_zone;
|
|
||||||
|
|
||||||
if( zone->GetFillMode() == ZFM_SEGMENTS )
|
status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
|
||||||
{
|
} while( status != std::future_status::ready );
|
||||||
ZONE_SEGMENT_FILL segFill;
|
}
|
||||||
|
|
||||||
fillZoneWithSegments( zone, zone->GetFilledPolysList(), segFill );
|
|
||||||
zone->SetFillSegments( segFill );
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
m_progressReporter->AdvanceProgress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
threadsFinished++;
|
|
||||||
} );
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Finalize the triangulation threads
|
|
||||||
while( threadsFinished < parallelThreadCount )
|
|
||||||
{
|
|
||||||
if( m_progressReporter )
|
|
||||||
m_progressReporter->KeepRefreshing();
|
|
||||||
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
if( m_progressReporter )
|
||||||
{
|
{
|
||||||
m_progressReporter->AdvancePhase();
|
m_progressReporter->AdvancePhase();
|
||||||
|
|
Loading…
Reference in New Issue