Fix a threading segfault when filling zones
The shape cache gets reset by the zone fill algorithm. This needs to be cleaned before multiple threads are created and cannot be modified when threading. Fixes https://gitlab.com/kicad/code/kicad/issues/4723
This commit is contained in:
parent
f5842156a5
commit
224b41e8b1
|
@ -193,7 +193,7 @@ void D_PAD::SetChamferRectRatio( double aChamferScale )
|
||||||
const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
|
const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
|
||||||
{
|
{
|
||||||
if( m_shapesDirty )
|
if( m_shapesDirty )
|
||||||
buildEffectiveShapes();
|
BuildEffectiveShapes();
|
||||||
|
|
||||||
return m_effectiveShapes;
|
return m_effectiveShapes;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ const std::vector<std::shared_ptr<SHAPE>>& D_PAD::GetEffectiveShapes() const
|
||||||
const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
|
const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
|
||||||
{
|
{
|
||||||
if( m_shapesDirty )
|
if( m_shapesDirty )
|
||||||
buildEffectiveShapes();
|
BuildEffectiveShapes();
|
||||||
|
|
||||||
return m_effectiveHoleShape;
|
return m_effectiveHoleShape;
|
||||||
}
|
}
|
||||||
|
@ -211,13 +211,13 @@ const std::shared_ptr<SHAPE_SEGMENT>& D_PAD::GetEffectiveHoleShape() const
|
||||||
int D_PAD::GetBoundingRadius() const
|
int D_PAD::GetBoundingRadius() const
|
||||||
{
|
{
|
||||||
if( m_shapesDirty )
|
if( m_shapesDirty )
|
||||||
buildEffectiveShapes();
|
BuildEffectiveShapes();
|
||||||
|
|
||||||
return m_effectiveBoundingRadius;
|
return m_effectiveBoundingRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::buildEffectiveShapes() const
|
void D_PAD::BuildEffectiveShapes() const
|
||||||
{
|
{
|
||||||
m_effectiveShapes.clear();
|
m_effectiveShapes.clear();
|
||||||
m_effectiveHoleShape = nullptr;
|
m_effectiveHoleShape = nullptr;
|
||||||
|
|
|
@ -317,6 +317,8 @@ public:
|
||||||
void SetDrillShape( PAD_DRILL_SHAPE_T aShape ) { m_drillShape = aShape; m_shapesDirty = true; }
|
void SetDrillShape( PAD_DRILL_SHAPE_T aShape ) { m_drillShape = aShape; m_shapesDirty = true; }
|
||||||
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
|
PAD_DRILL_SHAPE_T GetDrillShape() const { return m_drillShape; }
|
||||||
|
|
||||||
|
bool IsDirty() const { return m_shapesDirty; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JEY TODO: temporary until Tom is done with DRC stuff....
|
* JEY TODO: temporary until Tom is done with DRC stuff....
|
||||||
*/
|
*/
|
||||||
|
@ -575,6 +577,11 @@ public:
|
||||||
*/
|
*/
|
||||||
bool PadShouldBeNPTH() const;
|
bool PadShouldBeNPTH() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuilds the shape cache for the pad and clears the dirty bit
|
||||||
|
*/
|
||||||
|
void BuildEffectiveShapes() const;
|
||||||
|
|
||||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||||
|
|
||||||
virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
|
||||||
|
@ -597,8 +604,6 @@ private:
|
||||||
|
|
||||||
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
|
void addPadPrimitivesToPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError ) const;
|
||||||
|
|
||||||
void buildEffectiveShapes() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxString m_name; ///< pad name (pin number in schematic)
|
wxString m_name; ///< pad name (pin number in schematic)
|
||||||
wxString m_pinFunction; ///< pin function in schematic
|
wxString m_pinFunction; ///< pin function in schematic
|
||||||
|
|
|
@ -119,6 +119,16 @@ bool ZONE_FILLER::Fill( const std::vector<ZONE_CONTAINER*>& aZones, bool aCheck
|
||||||
m_boardOutline.RemoveAllContours();
|
m_boardOutline.RemoveAllContours();
|
||||||
m_brdOutlinesValid = m_board->GetBoardPolygonOutlines( m_boardOutline );
|
m_brdOutlinesValid = m_board->GetBoardPolygonOutlines( m_boardOutline );
|
||||||
|
|
||||||
|
// Update the bounding box shape caches in the pads to prevent multi-threaded rebuilds
|
||||||
|
for( auto module : m_board->Modules() )
|
||||||
|
{
|
||||||
|
for( auto pad : module->Pads() )
|
||||||
|
{
|
||||||
|
if( pad->IsDirty() )
|
||||||
|
pad->BuildEffectiveShapes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for( auto zone : aZones )
|
for( auto zone : aZones )
|
||||||
{
|
{
|
||||||
// Keepout zones are not filled
|
// Keepout zones are not filled
|
||||||
|
@ -949,16 +959,14 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone, PCB_LAYER_ID
|
||||||
//
|
//
|
||||||
// We use the bounding-box to lay out the spokes, but for this to work the
|
// We use the bounding-box to lay out the spokes, but for this to work the
|
||||||
// bounding box has to be built at the same rotation as the spokes.
|
// bounding box has to be built at the same rotation as the spokes.
|
||||||
|
// We have to use a dummy pad to avoid dirtying the cached shapes
|
||||||
wxPoint shapePos = pad->ShapePos();
|
wxPoint shapePos = pad->ShapePos();
|
||||||
wxPoint padPos = pad->GetPosition();
|
double padAngle = pad->GetOrientation();
|
||||||
double padAngle = pad->GetOrientation();
|
D_PAD dummy_pad( *pad );
|
||||||
pad->SetOrientation( 0.0 );
|
dummy_pad.SetOrientation( 0.0 );
|
||||||
pad->SetPosition( { 0, 0 } );
|
dummy_pad.SetPosition( { 0, 0 } );
|
||||||
BOX2I reliefBB = pad->GetBoundingBox();
|
|
||||||
pad->SetPosition( padPos );
|
|
||||||
pad->SetOrientation( padAngle );
|
|
||||||
|
|
||||||
|
BOX2I reliefBB = dummy_pad.GetBoundingBox();
|
||||||
reliefBB.Inflate( thermalReliefGap + epsilon );
|
reliefBB.Inflate( thermalReliefGap + epsilon );
|
||||||
|
|
||||||
// For circle pads, the thermal spoke orientation is 45 deg
|
// For circle pads, the thermal spoke orientation is 45 deg
|
||||||
|
|
Loading…
Reference in New Issue