pcbnew: refactor connectivity locking

Locks protect the std::set in each item.  Devolving the mutex to the
CN_ITEM allows multiple threads to make simultaneous connections to
different items where they do not conflict.
This commit is contained in:
Seth Hillbrand 2018-10-12 17:06:10 -07:00
parent 59adb109a6
commit 4a730e6c54
3 changed files with 18 additions and 42 deletions

View File

@ -233,7 +233,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
i < dirtyItems.size();
i = nextItem.fetch_add( 1 ) )
{
CN_VISITOR visitor( dirtyItems[i], &m_listLock );
CN_VISITOR visitor( dirtyItems[i] );
m_itemList.FindNearby( dirtyItems[i], visitor );
if( m_progressReporter )
@ -597,8 +597,8 @@ void CN_VISITOR::checkZoneItemConnection( CN_ZONE* aZone, CN_ITEM* aItem )
( aItem->Parent()->Type() == PCB_TRACE_T &&
zoneItem->ContainsPoint( aItem->GetAnchor( 1 ) ) ) )
{
std::lock_guard<std::mutex> lock( *m_listLock );
CN_ITEM::Connect( zoneItem, aItem );
zoneItem->Connect( aItem );
aItem->Connect( zoneItem );
}
}
@ -622,8 +622,8 @@ void CN_VISITOR::checkZoneZoneConnection( CN_ZONE* aZoneA, CN_ZONE* aZoneB )
{
if( aZoneB->ContainsPoint( outline.CPoint( i ) ) )
{
std::lock_guard<std::mutex> lock( *m_listLock );
CN_ITEM::Connect( aZoneA, aZoneB );
aZoneA->Connect( aZoneB );
aZoneB->Connect( aZoneA );
return;
}
}
@ -634,8 +634,8 @@ void CN_VISITOR::checkZoneZoneConnection( CN_ZONE* aZoneA, CN_ZONE* aZoneB )
{
if( aZoneA->ContainsPoint( outline2.CPoint( i ) ) )
{
std::lock_guard<std::mutex> lock( *m_listLock );
CN_ITEM::Connect( aZoneA, aZoneB );
aZoneA->Connect( aZoneB );
aZoneB->Connect( aZoneA );
return;
}
}
@ -693,8 +693,8 @@ bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
( parentA->Type() == PCB_TRACE_T && parentB->HitTest( ptA2 ) ) ||
( parentB->Type() == PCB_TRACE_T && parentA->HitTest( ptB2 ) ) )
{
std::lock_guard<std::mutex> lock( *m_listLock );
CN_ITEM::Connect( m_item, aCandidate );
m_item->Connect( aCandidate );
aCandidate->Connect( m_item );
}
return true;

View File

@ -115,7 +115,7 @@ private:
class ITEM_MAP_ENTRY
{
public:
public:
ITEM_MAP_ENTRY( CN_ITEM* aItem = nullptr )
{
if( aItem )
@ -143,11 +143,8 @@ public:
std::list<CN_ITEM*> m_items;
};
std::mutex m_listLock;
CN_LIST m_itemList;
using ITEM_MAP_PAIR = std::pair <const BOARD_CONNECTED_ITEM*, ITEM_MAP_ENTRY>;
std::unordered_map<const BOARD_CONNECTED_ITEM*, ITEM_MAP_ENTRY> m_itemMap;
CLUSTERS m_connClusters;
@ -252,9 +249,6 @@ public:
};
bool operator<( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b );
/**
* Struct CN_VISTOR
**/
@ -262,9 +256,8 @@ class CN_VISITOR {
public:
CN_VISITOR( CN_ITEM* aItem, std::mutex* aListLock ) :
m_item( aItem ),
m_listLock( aListLock )
CN_VISITOR( CN_ITEM* aItem ) :
m_item( aItem )
{}
bool operator()( CN_ITEM* aCandidate );
@ -277,10 +270,6 @@ protected:
///> the item we are looking for connections to
CN_ITEM* m_item;
///> the mutex protecting our connection list
std::mutex* m_listLock;
};
#endif

View File

@ -171,6 +171,9 @@ private:
///> valid flag, used to identify garbage items (we use lazy removal)
bool m_valid;
///> mutex protecting this item's connected_items set to allow parallel connection threads
std::mutex m_listLock;
protected:
///> dirty flag, used to identify recently added item not yet scanned into the connectivity search
bool m_dirty;
@ -267,17 +270,6 @@ public:
return Layers().Start();
}
/**
* Function LayersOverlap()
*
* Returns true if the set of layers spanned by aOther overlaps our
* layers.
*/
bool LayersOverlap( const CN_ITEM* aOther ) const
{
return Layers().Overlaps( aOther->Layers() );
}
const BOX2I& BBox()
{
if( m_dirty && m_valid )
@ -318,15 +310,10 @@ public:
return m_canChangeNet;
}
bool isConnected( CN_ITEM* aItem ) const
void Connect( CN_ITEM* b )
{
return ( m_connected.find( aItem ) != m_connected.end() );
}
static void Connect( CN_ITEM* a, CN_ITEM* b )
{
a->m_connected.insert( b );
b->m_connected.insert( a );
std::lock_guard<std::mutex> lock( m_listLock );
m_connected.insert( b );
}
void RemoveInvalidRefs();