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;
|
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 ];
|
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)
|
#if defined(DEBUG)
|
||||||
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
|
||||||
#endif
|
#endif
|
||||||
|
@ -863,7 +869,8 @@ private:
|
||||||
// while 90° will produce a +.
|
// while 90° will produce a +.
|
||||||
int m_thermalGap;
|
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
|
#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
|
EDA_ITEM* PCB_VIA::Clone() const
|
||||||
{
|
{
|
||||||
return new PCB_VIA( *this );
|
return new PCB_VIA( *this );
|
||||||
|
|
|
@ -368,7 +368,8 @@ public:
|
||||||
return aItem && PCB_VIA_T == aItem->Type();
|
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
|
bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override
|
||||||
{
|
{
|
||||||
|
@ -557,11 +558,17 @@ public:
|
||||||
m_zoneLayerConnections[ ii ] = ZLC_UNRESOLVED;
|
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 ];
|
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:
|
protected:
|
||||||
void swapData( BOARD_ITEM* aImage ) override;
|
void swapData( BOARD_ITEM* aImage ) override;
|
||||||
|
|
||||||
|
@ -579,7 +586,8 @@ private:
|
||||||
bool m_keepStartEndLayer; ///< Keep the start and end annular rings
|
bool m_keepStartEndLayer; ///< Keep the start and end annular rings
|
||||||
bool m_isFree; ///< "Free" vias don't get their nets auto-updated
|
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 )
|
if( layer < F_Cu || layer > B_Cu )
|
||||||
Expecting( "copper layer name" );
|
Expecting( "copper layer name" );
|
||||||
|
|
||||||
pad->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
pad->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -5450,7 +5450,7 @@ PCB_VIA* PCB_PARSER::parsePCB_VIA()
|
||||||
if( layer < F_Cu || layer > B_Cu )
|
if( layer < F_Cu || layer > B_Cu )
|
||||||
Expecting( "copper layer name" );
|
Expecting( "copper layer name" );
|
||||||
|
|
||||||
via->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
via->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -263,20 +263,20 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
if( !canFill )
|
if( !canFill )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
// Now we're ready to fill.
|
// 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() )
|
if( !zoneLock.owns_lock() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
SHAPE_POLY_SET fillPolys;
|
||||||
|
|
||||||
SHAPE_POLY_SET fillPolys;
|
if( !fillSingleZone( zone, layer, fillPolys ) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if( !fillSingleZone( zone, layer, fillPolys ) )
|
zone->SetFilledPolysList( layer, fillPolys );
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
zone->SetFilledPolysList( layer, fillPolys );
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
if( m_progressReporter )
|
||||||
m_progressReporter->AdvanceProgress();
|
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->Outline()->Collide( viaShape.get() ) )
|
||||||
{
|
{
|
||||||
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
||||||
via->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
via->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||||
else
|
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->Outline()->Collide( padShape.get() ) )
|
||||||
{
|
{
|
||||||
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
if( zone->GetFill( layer )->Collide( flashedShape.get() ) )
|
||||||
pad->ZoneConnectionCache( layer ) = ZLC_CONNECTED;
|
pad->SetZoneConnectionCache( layer, ZLC_CONNECTED );
|
||||||
else
|
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 =
|
auto tesselate_lambda =
|
||||||
[&]( std::pair<ZONE*, PCB_LAYER_ID> aFillItem ) -> int
|
[&]( std::pair<ZONE*, PCB_LAYER_ID> aFillItem ) -> int
|
||||||
{
|
{
|
||||||
|
|
||||||
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
PCB_LAYER_ID layer = aFillItem.second;
|
PCB_LAYER_ID layer = aFillItem.second;
|
||||||
ZONE* zone = aFillItem.first;
|
ZONE* zone = aFillItem.first;
|
||||||
|
|
||||||
zone->CacheTriangulation( layer );
|
{
|
||||||
|
std::unique_lock<std::mutex> zoneLock( zone->GetLock(), std::try_to_lock );
|
||||||
|
|
||||||
if( zone->IsOnCopperLayer() )
|
if( !zoneLock.owns_lock() )
|
||||||
cache_optionally_flashed_connections( zone, layer );
|
return 0;
|
||||||
|
|
||||||
|
zone->CacheTriangulation( layer );
|
||||||
|
|
||||||
|
if( zone->IsOnCopperLayer() )
|
||||||
|
cache_optionally_flashed_connections( zone, layer );
|
||||||
|
|
||||||
|
zone->SetFillFlag( layer, true );
|
||||||
|
}
|
||||||
|
|
||||||
zone->SetFillFlag( layer, true );
|
|
||||||
return 1;
|
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( status == std::future_status::ready )
|
||||||
{
|
{
|
||||||
if( ret.first.get() )
|
if( ret.first.get() ) // lambda completed
|
||||||
{
|
{
|
||||||
++finished;
|
++finished;
|
||||||
|
ret.second++; // go to next step
|
||||||
if( !cancelled && ret.second == 0 )
|
|
||||||
returns[ii].first = tp.submit( tesselate_lambda, toFill[ii] );
|
|
||||||
|
|
||||||
ret.second++;
|
|
||||||
}
|
}
|
||||||
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