Tighten lifecycle management of CN_ANCHOR/CN_ITEM.

In particular, when a CN_ITEM is freed set all its anchor's
item pointers to NULL.  (The anchors have a separate
lifecycle due to being std::shared_ptrs.)

Hopefully fixes Sentry KICAD-KV.

(cherry picked from commit 0eac5c6748)
This commit is contained in:
Jeff Young 2023-05-03 10:44:59 +01:00
parent ebc14b35f5
commit a3197578d6
1 changed files with 61 additions and 109 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* @author Maciej Suminski <maciej.suminski@cern.ch> * @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
@ -58,33 +58,23 @@ class CN_CLUSTER;
class CN_ANCHOR class CN_ANCHOR
{ {
public: public:
CN_ANCHOR() CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem ) :
{ m_pos( aPos ),
m_item = nullptr; m_item( aItem ),
} m_tag( -1 ),
m_noline( false )
CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem ) { }
{
m_pos = aPos;
m_item = aItem;
assert( m_item );
}
bool Valid() const; bool Valid() const;
bool Dirty() const; bool Dirty() const;
CN_ITEM* Item() const CN_ITEM* Item() const { return m_item; }
{ void SetItem( CN_ITEM* aItem ) { m_item = aItem; }
return m_item;
}
BOARD_CONNECTED_ITEM* Parent() const; BOARD_CONNECTED_ITEM* Parent() const;
const VECTOR2I& Pos() const const VECTOR2I& Pos() const { return m_pos; }
{
return m_pos;
}
void Move( const VECTOR2I& aPos ) void Move( const VECTOR2I& aPos )
{ {
@ -96,39 +86,16 @@ public:
return ( m_pos - aSecond.Pos() ).EuclideanNorm(); return ( m_pos - aSecond.Pos() ).EuclideanNorm();
} }
///< Return tag, common identifier for connected nodes. ///< @return tag, a common identifier for connected nodes.
inline int GetTag() const int GetTag() const { return m_tag; }
{ void SetTag( int aTag ) { m_tag = aTag; }
return m_tag;
}
///< Set tag, common identifier for connected nodes. ///< @return true if this node can be a target for ratsnest lines.
inline void SetTag( int aTag ) const bool& GetNoLine() const { return m_noline; }
{ void SetNoLine( bool aEnable ) { m_noline = aEnable; }
m_tag = aTag;
}
///< Decide whether this node can be a ratsnest line target. const std::shared_ptr<CN_CLUSTER>& GetCluster() const { return m_cluster; }
inline void SetNoLine( bool aEnable ) void SetCluster( std::shared_ptr<CN_CLUSTER>& aCluster ) { m_cluster = aCluster; }
{
m_noline = aEnable;
}
///< Return true if this node can be a target for ratsnest lines.
inline const bool& GetNoLine() const
{
return m_noline;
}
inline void SetCluster( std::shared_ptr<CN_CLUSTER>& aCluster )
{
m_cluster = aCluster;
}
inline const std::shared_ptr<CN_CLUSTER>& GetCluster() const
{
return m_cluster;
}
/** /**
* The anchor point is dangling if the parent is a track and this anchor point is not * The anchor point is dangling if the parent is a track and this anchor point is not
@ -148,10 +115,10 @@ public:
static const int TAG_UNCONNECTED = -1; static const int TAG_UNCONNECTED = -1;
private: private:
VECTOR2I m_pos; ///< Position of the anchor. VECTOR2I m_pos; ///< Position of the anchor.
CN_ITEM* m_item = nullptr; ///< Pad or track/arc/via owning the anchor. CN_ITEM* m_item; ///< Pad or track/arc/via owning the anchor.
int m_tag = -1; ///< Tag for quick connection resolution. int m_tag; ///< Tag for quick connection resolution.
bool m_noline = false; ///< Whether it the node can be a target for ratsnest lines. bool m_noline; ///< Whether it the node can be a target for ratsnest lines.
std::shared_ptr<CN_CLUSTER> m_cluster; ///< Cluster to which the anchor belongs. std::shared_ptr<CN_CLUSTER> m_cluster; ///< Cluster to which the anchor belongs.
}; };
@ -179,7 +146,11 @@ public:
m_connected.reserve( 8 ); m_connected.reserve( 8 );
} }
virtual ~CN_ITEM() {}; virtual ~CN_ITEM()
{
for( const std::shared_ptr<CN_ANCHOR>& anchor : m_anchors )
anchor->SetItem( nullptr );
};
std::shared_ptr<CN_ANCHOR> AddAnchor( const VECTOR2I& aPos ) std::shared_ptr<CN_ANCHOR> AddAnchor( const VECTOR2I& aPos )
{ {
@ -253,14 +224,11 @@ public:
virtual int AnchorCount() const; virtual int AnchorCount() const;
virtual const VECTOR2I GetAnchor( int n ) const; virtual const VECTOR2I GetAnchor( int n ) const;
int GetAnchorItemCount() const { return m_anchors.size(); }
std::shared_ptr<CN_ANCHOR> GetAnchorItem( int n ) const { return m_anchors[n]; }
int Net() const int Net() const
{ {
return ( !m_parent || !m_valid ) ? -1 : m_parent->GetNetCode(); return ( !m_parent || !m_valid ) ? -1 : m_parent->GetNetCode();
} }
///< allow parallel connection threads
protected: protected:
bool m_dirty; ///< used to identify recently added item not yet bool m_dirty; ///< used to identify recently added item not yet
///< scanned into the connectivity search ///< scanned into the connectivity search
@ -282,9 +250,10 @@ private:
}; };
typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR; /*
* Represents a single outline of a zone fill on a particular layer. \a aSubpolyIndex indicates
* which outline in the fill's SHAPE_POLY_SET.
*/
class CN_ZONE_LAYER : public CN_ITEM class CN_ZONE_LAYER : public CN_ITEM
{ {
public: public:
@ -354,15 +323,6 @@ public:
return m_triangulatedPoly->Outline( m_subpolyIndex ); return m_triangulatedPoly->Outline( m_subpolyIndex );
} }
VECTOR2I ClosestPoint( const VECTOR2I aPt )
{
VECTOR2I closest;
m_triangulatedPoly->SquaredDistanceToPolygon( aPt, m_subpolyIndex, &closest );
return closest;
}
bool Collide( SHAPE* aRefShape ) const bool Collide( SHAPE* aRefShape ) const
{ {
BOX2I bbox = aRefShape->BBox(); BOX2I bbox = aRefShape->BBox();
@ -401,14 +361,6 @@ private:
class CN_LIST class CN_LIST
{ {
protected:
std::vector<CN_ITEM*> m_items;
void addItemtoTree( CN_ITEM* item )
{
m_index.Insert( item );
}
public: public:
CN_LIST() CN_LIST()
{ {
@ -425,14 +377,11 @@ public:
m_index.RemoveAll(); m_index.RemoveAll();
} }
using ITER = decltype( m_items )::iterator; std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
using CONST_ITER = decltype( m_items )::const_iterator; std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
ITER begin() { return m_items.begin(); }; std::vector<CN_ITEM*>::const_iterator begin() const { return m_items.begin(); }
ITER end() { return m_items.end(); }; std::vector<CN_ITEM*>::const_iterator end() const { return m_items.end(); }
CONST_ITER begin() const { return m_items.begin(); }
CONST_ITER end() const { return m_items.end(); }
CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; } CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; }
@ -457,39 +406,34 @@ public:
SetDirty( false ); SetDirty( false );
} }
int Size() const int Size() const { return m_items.size(); }
{
return m_items.size();
}
CN_ITEM* Add( PAD* pad ); CN_ITEM* Add( PAD* pad );
CN_ITEM* Add( PCB_TRACK* track ); CN_ITEM* Add( PCB_TRACK* track );
CN_ITEM* Add( PCB_ARC* track ); CN_ITEM* Add( PCB_ARC* track );
CN_ITEM* Add( PCB_VIA* via ); CN_ITEM* Add( PCB_VIA* via );
CN_ITEM* Add( CN_ZONE_LAYER* zitem ); CN_ITEM* Add( CN_ZONE_LAYER* zitem );
const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer ); const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
protected:
void addItemtoTree( CN_ITEM* item )
{
m_index.Insert( item );
}
protected:
std::vector<CN_ITEM*> m_items;
private: private:
bool m_dirty; bool m_dirty;
bool m_hasInvalid; bool m_hasInvalid;
CN_RTREE<CN_ITEM*> m_index; CN_RTREE<CN_ITEM*> m_index;
}; };
class CN_CLUSTER class CN_CLUSTER
{ {
private:
bool m_conflicting;
int m_originNet;
CN_ITEM* m_originPad;
std::vector<CN_ITEM*> m_items;
std::unordered_map<int, int> m_netRanks;
public: public:
CN_CLUSTER(); CN_CLUSTER();
~CN_CLUSTER(); ~CN_CLUSTER();
@ -505,16 +449,24 @@ public:
int Size() const { return m_items.size(); } int Size() const { return m_items.size(); }
bool IsOrphaned() const { return m_originPad == nullptr; } bool IsOrphaned() const
{
return m_originPad == nullptr;
}
bool IsConflicting() const { return m_conflicting; } bool IsConflicting() const { return m_conflicting; }
void Add( CN_ITEM* item ); void Add( CN_ITEM* item );
using ITER = decltype(m_items)::iterator; std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
ITER begin() { return m_items.begin(); }; private:
ITER end() { return m_items.end(); }; bool m_conflicting;
int m_originNet;
CN_ITEM* m_originPad;
std::vector<CN_ITEM*> m_items;
std::unordered_map<int, int> m_netRanks;
}; };