Browse Source

Construction mgr: protect batch containers

These are added to from the activation delay thread, but
accessed from the tool thread (e.g. via computeAnchors)
so they should be protected from concurrent access.

Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/18835
pcb_db
John Beard 1 year ago
parent
commit
8f95211bbe
  1. 66
      common/tool/construction_manager.cpp
  2. 6
      include/tool/construction_manager.h

66
common/tool/construction_manager.cpp

@ -232,14 +232,30 @@ void CONSTRUCTION_MANAGER::ProposeConstructionItems( CONSTRUCTION_ITEM_BATCH aBa
void CONSTRUCTION_MANAGER::CancelProposal()
{
// static int i = 0;
// std::cout << "Cancelling proposal " << i++ << std::endl;
m_activationHelper->CancelProposal();
}
void CONSTRUCTION_MANAGER::acceptConstructionItems( PENDING_BATCH&& aAcceptedBatch )
{
const auto getInvolved = [&]( const CONSTRUCTION_ITEM_BATCH& aBatchToAdd )
{
for( const CONSTRUCTION_ITEM& item : aBatchToAdd )
{
// Only show the item if it's not already involved
// (avoid double-drawing the same item)
if( m_involvedItems.count( item.Item ) == 0 )
{
m_involvedItems.insert( item.Item );
}
}
};
// Copies for use outside the lock
std::vector<CONSTRUCTION_ITEM_BATCH> persistentBatches, temporaryBatches;
{
std::lock_guard<std::mutex> lock( m_batchesMutex );
if( aAcceptedBatch.IsPersistent )
{
// We only keep one previous persistent batch for the moment
@ -275,39 +291,41 @@ void CONSTRUCTION_MANAGER::acceptConstructionItems( PENDING_BATCH&& aAcceptedBat
m_temporaryConstructionBatches.emplace_back( std::move( aAcceptedBatch.Batch ) );
}
// Refresh what items are drawn
m_involvedItems.clear();
// Copy the batches for use outside the lock
if( m_persistentConstructionBatch )
{
getInvolved( *m_persistentConstructionBatch );
persistentBatches.push_back( *m_persistentConstructionBatch );
}
for( const CONSTRUCTION_ITEM_BATCH& batch : m_temporaryConstructionBatches )
{
getInvolved( batch );
temporaryBatches.push_back( batch );
}
}
KIGFX::CONSTRUCTION_GEOM& geom = m_viewHandler.GetViewItem();
geom.ClearDrawables();
m_involvedItems.clear();
const auto addBatchItems = [&]( const CONSTRUCTION_ITEM_BATCH& aBatchToAdd, bool aPersistent )
const auto addDrawables =
[&]( const std::vector<CONSTRUCTION_ITEM_BATCH>& aBatches, bool aIsPersistent )
{
for( const CONSTRUCTION_ITEM& item : aBatchToAdd )
for( const CONSTRUCTION_ITEM_BATCH& batch : aBatches )
{
// Only show the item if it's not already involved
// (avoid double-drawing the same item)
if( m_involvedItems.count( item.Item ) == 0 )
for( const CONSTRUCTION_ITEM& item : batch )
{
m_involvedItems.insert( item.Item );
for( const KIGFX::CONSTRUCTION_GEOM::DRAWABLE& construction : item.Constructions )
for( const KIGFX::CONSTRUCTION_GEOM::DRAWABLE& drawable : item.Constructions )
{
geom.AddDrawable( construction, aPersistent );
geom.AddDrawable( drawable, aIsPersistent );
}
}
}
};
if( m_persistentConstructionBatch )
{
addBatchItems( *m_persistentConstructionBatch, true );
}
for( const CONSTRUCTION_ITEM_BATCH& batch : m_temporaryConstructionBatches )
{
addBatchItems( batch, false );
}
addDrawables( persistentBatches, true );
addDrawables( temporaryBatches, false );
m_viewHandler.updateView();
}
@ -329,6 +347,7 @@ bool CONSTRUCTION_MANAGER::InvolvesAllGivenRealItems( const std::vector<EDA_ITEM
void CONSTRUCTION_MANAGER::GetConstructionItems(
std::vector<CONSTRUCTION_ITEM_BATCH>& aToExtend ) const
{
std::lock_guard<std::mutex> lock( m_batchesMutex );
if( m_persistentConstructionBatch )
{
aToExtend.push_back( *m_persistentConstructionBatch );
@ -342,6 +361,7 @@ void CONSTRUCTION_MANAGER::GetConstructionItems(
bool CONSTRUCTION_MANAGER::HasActiveConstruction() const
{
std::lock_guard<std::mutex> lock( m_batchesMutex );
return m_persistentConstructionBatch.has_value() || !m_temporaryConstructionBatches.empty();
}

6
include/tool/construction_manager.h

@ -24,8 +24,9 @@
*/
#pragma once
#include <vector>
#include <deque>
#include <mutex>
#include <vector>
#include <preview_items/construction_geom.h>
@ -206,6 +207,9 @@ private:
std::set<EDA_ITEM*> m_involvedItems;
std::unique_ptr<ACTIVATION_HELPER<PENDING_BATCH>> m_activationHelper;
// Protects the persistent and temporary construction batches
mutable std::mutex m_batchesMutex;
};

Loading…
Cancel
Save