Make sure tesselate_lambda has lock before modifying zone.
Also implements locking for upating pad & tracks' zoneConnectionCaches. Fixes https://gitlab.com/kicad/code/kicad/issues/13531
This commit is contained in:
parent
45a71a205c
commit
0c8f95aa02
11
pcbnew/pad.h
11
pcbnew/pad.h
|
@ -740,11 +740,17 @@ public:
|
|||
m_zoneLayerConnections[ ii ] = ZLC_UNRESOLVED;
|
||||
}
|
||||
|
||||
ZONE_LAYER_CONNECTION& ZoneConnectionCache( PCB_LAYER_ID aLayer ) const
|
||||
const ZONE_LAYER_CONNECTION& ZoneConnectionCache( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
return m_zoneLayerConnections[ aLayer ];
|
||||
}
|
||||
|
||||
void SetZoneConnectionCache( PCB_LAYER_ID aLayer, ZONE_LAYER_CONNECTION aConnection )
|
||||
{
|
||||
std::unique_lock<std::mutex> cacheLock( m_zoneLayerConnectionsMutex );
|
||||
m_zoneLayerConnections[ aLayer ] = aConnection;
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||
#endif
|
||||
|
@ -863,7 +869,8 @@ private:
|
|||
// while 90° will produce a +.
|
||||
int m_thermalGap;
|
||||
|
||||
mutable ZONE_LAYER_CONNECTION m_zoneLayerConnections[B_Cu + 1];
|
||||
std::mutex m_zoneLayerConnectionsMutex;
|
||||
ZONE_LAYER_CONNECTION m_zoneLayerConnections[B_Cu + 1];
|
||||
};
|
||||
|
||||
#endif // PAD_H
|
||||
|
|
|
@ -96,6 +96,36 @@ PCB_VIA::PCB_VIA( BOARD_ITEM* aParent ) :
|
|||
}
|
||||
|
||||
|
||||
PCB_VIA::PCB_VIA( const PCB_VIA& aOther ) :
|
||||
PCB_TRACK( aOther.GetParent(), PCB_VIA_T )
|
||||
{
|
||||
PCB_VIA::operator=( aOther );
|
||||
|
||||
const_cast<KIID&>( m_Uuid ) = aOther.m_Uuid;
|
||||
}
|
||||
|
||||
|
||||
PCB_VIA& PCB_VIA::operator=( const PCB_VIA &aOther )
|
||||
{
|
||||
BOARD_CONNECTED_ITEM::operator=( aOther );
|
||||
|
||||
m_Width = aOther.m_Width;
|
||||
m_Start = aOther.m_Start;
|
||||
m_End = aOther.m_End;
|
||||
m_CachedLOD = aOther.m_CachedLOD;
|
||||
m_CachedScale = aOther.m_CachedScale;
|
||||
|
||||
m_bottomLayer = aOther.m_bottomLayer;
|
||||
m_viaType = aOther.m_viaType;
|
||||
m_drill = aOther.m_drill;
|
||||
m_removeUnconnectedLayer = aOther.m_removeUnconnectedLayer;
|
||||
m_keepStartEndLayer = aOther.m_keepStartEndLayer;
|
||||
m_isFree = aOther.m_isFree;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
EDA_ITEM* PCB_VIA::Clone() const
|
||||
{
|
||||
return new PCB_VIA( *this );
|
||||
|
|
|
@ -368,7 +368,8 @@ public:
|
|||
return aItem && PCB_VIA_T == aItem->Type();
|
||||
}
|
||||
|
||||
// Do not create a copy constructor. The one generated by the compiler is adequate.
|
||||
PCB_VIA( const PCB_VIA& aOther );
|
||||
PCB_VIA& operator=( const PCB_VIA &aOther );
|
||||
|
||||
bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override
|
||||
{
|
||||
|
@ -557,11 +558,17 @@ public:
|
|||
m_zoneLayerConnections[ ii ] = ZLC_UNRESOLVED;
|
||||
}
|
||||
|
||||
ZONE_LAYER_CONNECTION& ZoneConnectionCache( PCB_LAYER_ID aLayer ) const
|
||||
const ZONE_LAYER_CONNECTION& ZoneConnectionCache( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
return m_zoneLayerConnections[ aLayer ];
|
||||
}
|
||||
|
||||
void SetZoneConnectionCache( PCB_LAYER_ID aLayer, ZONE_LAYER_CONNECTION aConnection )
|
||||
{
|
||||
std::unique_lock<std::mutex> cacheLock( m_zoneLayerConnectionsMutex );
|
||||
m_zoneLayerConnections[ aLayer ] = aConnection;
|
||||
}
|
||||
|
||||
protected:
|
||||
void swapData( BOARD_ITEM* aImage ) override;
|
||||
|
||||
|
@ -579,7 +586,8 @@ private:
|
|||
bool m_keepStartEndLayer; ///< Keep the start and end annular rings
|
||||
bool m_isFree; ///< "Free" vias don't get their nets auto-updated
|
||||
|
||||
mutable ZONE_LAYER_CONNECTION m_zoneLayerConnections[B_Cu + 1];
|
||||
std::mutex m_zoneLayerConnectionsMutex;
|
||||
ZONE_LAYER_CONNECTION m_zoneLayerConnections[B_Cu + 1];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5026,7 +5026,7 @@ PAD* PCB_PARSER::parsePAD( FOOTPRINT* aParent )
|
|||
if( layer < F_Cu || layer > B_Cu )
|
||||
Expecting( "copper layer name" );
|
||||
|
||||
pad->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
||||
pad->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -5450,7 +5450,7 @@ PCB_VIA* PCB_PARSER::parsePCB_VIA()
|
|||
if( layer < F_Cu || layer > B_Cu )
|
||||
Expecting( "copper layer name" );
|
||||
|
||||
via->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
||||
via->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -263,20 +263,20 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
|||
if( !canFill )
|
||||
return 0;
|
||||
|
||||
|
||||
// Now we're ready to fill.
|
||||
std::unique_lock<std::mutex> zoneLock( zone->GetLock(), std::try_to_lock );
|
||||
{
|
||||
std::unique_lock<std::mutex> zoneLock( zone->GetLock(), std::try_to_lock );
|
||||
|
||||
if( !zoneLock.owns_lock() )
|
||||
return 0;
|
||||
if( !zoneLock.owns_lock() )
|
||||
return 0;
|
||||
|
||||
SHAPE_POLY_SET fillPolys;
|
||||
|
||||
SHAPE_POLY_SET fillPolys;
|
||||
if( !fillSingleZone( zone, layer, fillPolys ) )
|
||||
return 0;
|
||||
|
||||
if( !fillSingleZone( zone, layer, fillPolys ) )
|
||||
return 0;
|
||||
|
||||
zone->SetFilledPolysList( layer, fillPolys );
|
||||
zone->SetFilledPolysList( layer, fillPolys );
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
m_progressReporter->AdvanceProgress();
|
||||
|
@ -314,9 +314,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
|||
if( zone->Outline()->Collide( viaShape.get() ) )
|
||||
{
|
||||
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
||||
via->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
||||
via->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||
else
|
||||
via->ZoneConnectionCache( layer ) = ZLC_UNCONNECTED;
|
||||
via->SetZoneConnectionCache( layer, ZLC_UNCONNECTED );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,9 +341,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
|||
if( zone->Outline()->Collide( padShape.get() ) )
|
||||
{
|
||||
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
||||
pad->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
||||
pad->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||
else
|
||||
pad->ZoneConnectionCache( layer ) = ZLC_UNCONNECTED;
|
||||
pad->SetZoneConnectionCache( layer, ZLC_UNCONNECTED );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,19 +353,26 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
|||
auto tesselate_lambda =
|
||||
[&]( std::pair<ZONE*, PCB_LAYER_ID> aFillItem ) -> int
|
||||
{
|
||||
|
||||
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||
return 0;
|
||||
|
||||
PCB_LAYER_ID layer = aFillItem.second;
|
||||
ZONE* zone = aFillItem.first;
|
||||
|
||||
zone->CacheTriangulation( layer );
|
||||
{
|
||||
std::unique_lock<std::mutex> zoneLock( zone->GetLock(), std::try_to_lock );
|
||||
|
||||
if( zone->IsOnCopperLayer() )
|
||||
cache_optionally_flashed_connections( zone, layer );
|
||||
if( !zoneLock.owns_lock() )
|
||||
return 0;
|
||||
|
||||
zone->CacheTriangulation( layer );
|
||||
|
||||
if( zone->IsOnCopperLayer() )
|
||||
cache_optionally_flashed_connections( zone, layer );
|
||||
|
||||
zone->SetFillFlag( layer, true );
|
||||
}
|
||||
|
||||
zone->SetFillFlag( layer, true );
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
@ -394,18 +401,19 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
|||
|
||||
if( status == std::future_status::ready )
|
||||
{
|
||||
if( ret.first.get() )
|
||||
if( ret.first.get() ) // lambda completed
|
||||
{
|
||||
++finished;
|
||||
|
||||
if( !cancelled && ret.second == 0 )
|
||||
returns[ii].first = tp.submit( tesselate_lambda, toFill[ii] );
|
||||
|
||||
ret.second++;
|
||||
ret.second++; // go to next step
|
||||
}
|
||||
else if( !cancelled )
|
||||
|
||||
if( !cancelled )
|
||||
{
|
||||
returns[ii].first = tp.submit( fill_lambda, toFill[ii] );
|
||||
// Queue the next step (will re-queue the existing step if it didn't complete)
|
||||
if( ret.second == 0 )
|
||||
returns[ii].first = tp.submit( fill_lambda, toFill[ii] );
|
||||
else if( ret.second == 1 )
|
||||
returns[ii].first = tp.submit( tesselate_lambda, toFill[ii] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue