From 5aa8af1abf2b316e64a212de880cc3f86c84e4ab Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Mon, 25 Mar 2024 21:58:02 -0400 Subject: [PATCH] Add a cache for looking up board items by ID --- include/kiid.h | 8 ++++++ pcbnew/board.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++--- pcbnew/board.h | 3 +++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/include/kiid.h b/include/kiid.h index 9fcaf8b2d0..896d0e2031 100644 --- a/include/kiid.h +++ b/include/kiid.h @@ -228,4 +228,12 @@ KICOMMON_API void to_json( nlohmann::json& aJson, const KIID& aKIID ); KICOMMON_API void from_json( const nlohmann::json& aJson, KIID& aKIID ); +template<> struct KICOMMON_API std::hash +{ + std::size_t operator()( const KIID& aId ) const + { + return aId.Hash(); + } +}; + #endif // KIID_H diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 186a7f0cd7..583d7db375 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -149,6 +149,8 @@ BOARD::~BOARD() item->SetParentGroup( nullptr ); } + m_itemByIdCache.clear(); + // Clean up the owned elements DeleteMARKERs(); @@ -896,6 +898,8 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity return; } + m_itemByIdCache.insert( { aBoardItem->m_Uuid, aBoardItem } ); + switch( aBoardItem->Type() ) { case PCB_NETINFO_T: @@ -941,12 +945,20 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity break; case PCB_FOOTPRINT_T: - if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND ) - m_footprints.push_back( static_cast( aBoardItem ) ); - else - m_footprints.push_front( static_cast( aBoardItem ) ); + { + FOOTPRINT* footprint = static_cast( aBoardItem ); + if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND ) + m_footprints.push_back( footprint ); + else + m_footprints.push_front( footprint ); + + footprint->RunOnChildren( [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); + } ); break; + } case PCB_DIM_ALIGNED_T: case PCB_DIM_CENTER_T: @@ -960,12 +972,24 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity case PCB_TEXTBOX_T: case PCB_TABLE_T: case PCB_TARGET_T: + { if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND ) m_drawings.push_back( aBoardItem ); else m_drawings.push_front( aBoardItem ); + if( aBoardItem->Type() == PCB_TABLE_T ) + { + PCB_TABLE* table = static_cast( aBoardItem ); + + table->RunOnChildren( [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); + } ); + } + break; + } // other types may use linked list default: @@ -1009,6 +1033,8 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) // find these calls and fix them! Don't send me no stinking' nullptr. wxASSERT( aBoardItem ); + m_itemByIdCache.erase( aBoardItem->m_Uuid ); + switch( aBoardItem->Type() ) { case PCB_NETINFO_T: @@ -1043,8 +1069,17 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) break; case PCB_FOOTPRINT_T: + { alg::delete_matching( m_footprints, aBoardItem ); + FOOTPRINT* footprint = static_cast( aBoardItem ); + + footprint->RunOnChildren( [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.erase( aChild->m_Uuid ); + } ); + break; + } case PCB_TRACE_T: case PCB_ARC_T: @@ -1064,8 +1099,21 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) case PCB_TEXTBOX_T: case PCB_TABLE_T: case PCB_TARGET_T: + { alg::delete_matching( m_drawings, aBoardItem ); + + if( aBoardItem->Type() == PCB_TABLE_T ) + { + PCB_TABLE* table = static_cast( aBoardItem ); + + table->RunOnChildren( [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.erase( aChild->m_Uuid ); + } ); + } + break; + } // other types may use linked list default: @@ -1166,6 +1214,9 @@ void BOARD::RemoveAll( std::initializer_list aTypes ) } } + for( BOARD_ITEM* item : removed ) + m_itemByIdCache.erase( item->m_Uuid ); + FinalizeBulkRemove( removed ); } @@ -1239,7 +1290,10 @@ void BOARD::DeleteAllFootprints() m_skipMaxClearanceCacheUpdate = true; for( FOOTPRINT* footprint : m_footprints ) + { + m_itemByIdCache.erase( footprint->m_Uuid ); delete footprint; + } m_footprints.clear(); m_skipMaxClearanceCacheUpdate = false; @@ -1252,6 +1306,9 @@ BOARD_ITEM* BOARD::GetItem( const KIID& aID ) const if( aID == niluuid ) return nullptr; + if( m_itemByIdCache.count( aID ) ) + return m_itemByIdCache.at( aID ); + for( PCB_TRACK* track : Tracks() ) { if( track->m_Uuid == aID ) diff --git a/pcbnew/board.h b/pcbnew/board.h index 169dd69d27..f636fb725b 100644 --- a/pcbnew/board.h +++ b/pcbnew/board.h @@ -1290,6 +1290,9 @@ private: ZONES m_zones; GENERATORS m_generators; + // Cache for fast access to items in the containers above by KIID, including children + std::unordered_map m_itemByIdCache; + LAYER m_layers[PCB_LAYER_ID_COUNT]; HIGH_LIGHT_INFO m_highLight; // current high light data