diff --git a/common/tool/construction_manager.cpp b/common/tool/construction_manager.cpp index 8e4905ac07..22106d5871 100644 --- a/common/tool/construction_manager.cpp +++ b/common/tool/construction_manager.cpp @@ -67,7 +67,7 @@ public: } } - void ProposeActivation( T&& aProposal, std::size_t aProposalTag ) + void ProposeActivation( T&& aProposal, std::size_t aProposalTag, bool aAcceptImmediately ) { std::lock_guard lock( m_mutex ); @@ -86,7 +86,11 @@ public: m_pendingProposalTag = aProposalTag; m_lastProposal = std::move( aProposal ); - m_proposalDeadline = std::chrono::steady_clock::now() + m_timeout; + m_proposalDeadline = std::chrono::steady_clock::now(); + + if( !aAcceptImmediately ) + m_proposalDeadline += m_timeout; + m_cv.notify_all(); } @@ -224,19 +228,28 @@ void CONSTRUCTION_MANAGER::ProposeConstructionItems( return; } - auto pendingBatch = std::make_unique( PENDING_BATCH{ std::move( *aBatch ), - aIsPersistent } ); + bool acceptImmediately = false; - if( aIsPersistent ) { - // If the batch is persistent, we can accept it immediately - acceptConstructionItems( std::move( pendingBatch ) ); - } - else - { - const std::size_t hash = HashConstructionBatchSources( pendingBatch->Batch, aIsPersistent ); - m_activationHelper->ProposeActivation( std::move( pendingBatch ), hash ); + std::lock_guard lock( m_batchesMutex ); + + if( aIsPersistent ) + { + acceptImmediately = true; + } + else + { + // If the batch is temporary, we can accept it immediately if there's room + acceptImmediately = m_temporaryConstructionBatches.size() < getMaxTemporaryBatches(); + } } + + auto pendingBatch = + std::make_unique( PENDING_BATCH{ std::move( *aBatch ), aIsPersistent } ); + const std::size_t hash = HashConstructionBatchSources( pendingBatch->Batch, aIsPersistent ); + + // Immediate or not, propose the batch via the activation helper as this handles duplicates + m_activationHelper->ProposeActivation( std::move( pendingBatch ), hash, acceptImmediately ); } @@ -246,6 +259,14 @@ void CONSTRUCTION_MANAGER::CancelProposal() } +unsigned CONSTRUCTION_MANAGER::getMaxTemporaryBatches() const +{ + // We only keep up to one previous temporary batch and the current one + // we could make this a setting if we want to keep more, but it gets cluttered + return 2; +} + + void CONSTRUCTION_MANAGER::acceptConstructionItems( std::unique_ptr aAcceptedBatch ) { const auto getInvolved = [&]( const CONSTRUCTION_ITEM_BATCH& aBatchToAdd ) @@ -289,11 +310,7 @@ void CONSTRUCTION_MANAGER::acceptConstructionItems( std::unique_ptr= maxTempItems ) + while( m_temporaryConstructionBatches.size() >= getMaxTemporaryBatches() ) { m_temporaryConstructionBatches.pop_front(); } diff --git a/include/tool/construction_manager.h b/include/tool/construction_manager.h index 410fcfdc8f..680843aa72 100644 --- a/include/tool/construction_manager.h +++ b/include/tool/construction_manager.h @@ -201,6 +201,13 @@ private: void acceptConstructionItems( std::unique_ptr aAcceptedBatchHash ); + /** + * How many batches of temporary construction items can be active at once. + * + * This is to prevent too much clutter. + */ + unsigned getMaxTemporaryBatches() const; + CONSTRUCTION_VIEW_HANDLER& m_viewHandler; /// Within one "operation", there is one set of construction items that are