change m_CachesMutex to shared_mutex and do shared locking for read access in zone BBox calculations

This commit is contained in:
Armin Schoisswohl 2024-03-06 15:26:30 +01:00 committed by Jeff Young
parent aff3064187
commit 1f1b97212b
7 changed files with 43 additions and 27 deletions

View File

@ -262,7 +262,7 @@ void BOARD::IncrementTimeStamp()
|| !m_ZoneBBoxCache.empty()
|| m_CopperItemRTreeCache )
{
std::unique_lock<std::mutex> cacheLock( m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( m_CachesMutex );
m_IntersectsAreaCache.clear();
m_EnclosedByAreaCache.clear();

View File

@ -35,7 +35,7 @@
#include <pcb_plot_params.h>
#include <title_block.h>
#include <tools/pcb_selection.h>
#include <mutex>
#include <shared_mutex>
#include <list>
class BOARD_DESIGN_SETTINGS;
@ -1227,7 +1227,7 @@ public:
};
// ------------ Run-time caches -------------
std::mutex m_CachesMutex;
std::shared_mutex m_CachesMutex;
std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_IntersectsCourtyardCache;
std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_IntersectsFCourtyardCache;
std::unordered_map<PTR_PTR_CACHE_KEY, bool> m_IntersectsBCourtyardCache;

View File

@ -136,7 +136,7 @@ bool DRC_CACHE_GENERATOR::Run()
std::future<void> retn = tp.submit(
[&]()
{
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( m_board->m_CachesMutex );
if( !m_board->m_CopperItemRTreeCache )
m_board->m_CopperItemRTreeCache = std::make_shared<DRC_RTREE>();
@ -184,7 +184,7 @@ bool DRC_CACHE_GENERATOR::Run()
rtree->Insert( aZone, layer );
}
std::unique_lock<std::mutex> cacheLock( m_board->m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( m_board->m_CachesMutex );
m_board->m_CopperZoneRTreeCache[ aZone ] = std::move( rtree );
done.fetch_add( 1 );

View File

@ -153,7 +153,7 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
PTR_PTR_LAYER_CACHE_KEY key = { ruleArea, copperZone, UNDEFINED_LAYER };
{
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
board->m_IntersectsAreaCache[ key ] = isInside;
}

View File

@ -57,12 +57,12 @@ public:
// in the ENUM_MAP: one for the canonical layer name and one for the user layer name.
// We need to check against both.
wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices();
const wxString& layerName = b->AsString();
BOARD* board = static_cast<PCBEXPR_CONTEXT*>( aCtx )->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
auto i = board->m_LayerExpressionCache.find( layerName );
LSET mask;
wxPGChoices& layerMap = ENUM_MAP<PCB_LAYER_ID>::Instance().Choices();
const wxString& layerName = b->AsString();
BOARD* board = static_cast<PCBEXPR_CONTEXT*>( aCtx )->GetBoard();
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
auto i = board->m_LayerExpressionCache.find( layerName );
LSET mask;
if( i == board->m_LayerExpressionCache.end() )
{

View File

@ -135,7 +135,7 @@ static void existsOnLayerFunc( LIBEVAL::CONTEXT* aCtx, void *self )
*/
BOARD* board = item->GetBoard();
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
auto i = board->m_LayerExpressionCache.find( layerName );
LSET mask;
@ -271,8 +271,8 @@ static void intersectsCourtyardFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( searchFootprints( board, arg->AsString(), context,
[&]( FOOTPRINT* fp )
{
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{
@ -331,8 +331,8 @@ static void intersectsFrontCourtyardFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( searchFootprints( board, arg->AsString(), context,
[&]( FOOTPRINT* fp )
{
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{
@ -390,8 +390,8 @@ static void intersectsBackCourtyardFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( searchFootprints( board, arg->AsString(), context,
[&]( FOOTPRINT* fp )
{
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
PTR_PTR_CACHE_KEY key = { fp, item };
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{
@ -660,7 +660,7 @@ static void intersectsAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self )
{
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::shared_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
key = { aArea, item, layer };
auto i = board->m_IntersectsAreaCache.find( key );
@ -673,7 +673,7 @@ static void intersectsAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
board->m_IntersectsAreaCache[ key ] = collides;
}
@ -735,8 +735,8 @@ static void enclosedByAreaFunc( LIBEVAL::CONTEXT* aCtx, void* self )
if( !aArea->GetBoundingBox().Intersects( itemBBox ) )
return false;
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
PTR_PTR_LAYER_CACHE_KEY key = { aArea, item, layer };
std::unique_lock<std::shared_mutex> cacheLock( board->m_CachesMutex );
PTR_PTR_LAYER_CACHE_KEY key = { aArea, item, layer };
if( ( item->GetFlags() & ROUTER_TRANSIENT ) == 0 )
{

View File

@ -344,13 +344,24 @@ const BOX2I ZONE::GetBoundingBox() const
if( const BOARD* board = GetBoard() )
{
std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
std::unique_lock<std::mutex> cacheLock( const_cast<BOARD*>( board )->m_CachesMutex );
std::shared_lock<std::shared_mutex> readLock( const_cast<BOARD*>( board )->m_CachesMutex );
auto cacheIter = cache.find( this );
if( cacheIter != cache.end() )
return cacheIter->second;
readLock.unlock();
// if we get here we need an exclusive lock to cache the entry
std::unique_lock<std::shared_mutex> writeLock( const_cast<BOARD*>( board )->m_CachesMutex );
// check again for the cached item; it might have been computed meanwhile by another thread
cacheIter = cache.find( this );
if( cacheIter != cache.end() )
return cacheIter->second;
BOX2I bbox = m_Poly->BBox();
cache[ this ] = bbox;
return bbox;
@ -364,11 +375,16 @@ void ZONE::CacheBoundingBox()
{
BOARD* board = GetBoard();
std::unordered_map<const ZONE*, BOX2I>& cache = board->m_ZoneBBoxCache;
std::unique_lock<std::mutex> cacheLock( board->m_CachesMutex );
std::shared_lock<std::shared_mutex> readLock( board->m_CachesMutex );
auto cacheIter = cache.find( this );
if( cacheIter == cache.end() )
cache[ this ] = m_Poly->BBox();
if( cacheIter == cache.end() ) {
readLock.unlock();
std::unique_lock<std::shared_mutex> writeLock(board->m_CachesMutex);
// check again in case another thread has already calculated the entry while we were waiting for the exclusive lock
if ( cache.count( this ) == 0 )
cache[this] = m_Poly->BBox();
}
}