diff --git a/pcbnew/pad.h b/pcbnew/pad.h index 2d58f28bca..838d568070 100644 --- a/pcbnew/pad.h +++ b/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 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 diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index b92ba0ae9c..22933ad963 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -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( 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 ); diff --git a/pcbnew/pcb_track.h b/pcbnew/pcb_track.h index e0ae4484d0..b1fb13401f 100644 --- a/pcbnew/pcb_track.h +++ b/pcbnew/pcb_track.h @@ -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& 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 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]; }; diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp index 13826cb722..bf96a7b828 100644 --- a/pcbnew/plugins/kicad/pcb_parser.cpp +++ b/pcbnew/plugins/kicad/pcb_parser.cpp @@ -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; diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 73e6d6e320..b9dbb62bcf 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -263,20 +263,20 @@ bool ZONE_FILLER::Fill( std::vector& aZones, bool aCheck, wxWindow* aPare if( !canFill ) return 0; - // Now we're ready to fill. - std::unique_lock zoneLock( zone->GetLock(), std::try_to_lock ); + { + std::unique_lock 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& 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& 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& aZones, bool aCheck, wxWindow* aPare auto tesselate_lambda = [&]( std::pair 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 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& 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] ); } } }