diff --git a/GaudiExamples/src/CounterEx/CounterAlg.cpp b/GaudiExamples/src/CounterEx/CounterAlg.cpp index 6d2b8ed178c3d9cdb54f84f78e773a0f0a9c0a75..21b26a8be795958ed69b44a4f539d83cb26a0c1d 100644 --- a/GaudiExamples/src/CounterEx/CounterAlg.cpp +++ b/GaudiExamples/src/CounterEx/CounterAlg.cpp @@ -13,6 +13,10 @@ #include "GaudiAlg/Consumer.h" +#include <fmt/format.h> +#include <deque> +#include <mutex> + /// Simple algorithm illustrating the usage of different "counters" struct CounterAlg : Gaudi::Functional::Consumer<void()> { @@ -28,6 +32,21 @@ struct CounterAlg : Gaudi::Functional::Consumer<void()> { ++msg; avg_int += 1; avg_noAto += 1.5; + // update counters in the deque, creating new ones for the first 20 events + // and dropping first 10 in the next 10 events + { + // needs to be protected by a mutex in case of multithreaded usage as the + // deque is not thread safe + std::scoped_lock lock(counterDequeMutex); + if ( counterCount < 20 ) { + counterDeque.emplace_back( this, fmt::format( "DQCounter{}", counterDeque.size() ) ); + counterCount++; + } + if ( counterCount == 20 && counterDeque.size() > 10 ) { + counterDeque.pop_front(); + } + for ( auto& c : counterDeque ) c++; + } } // declare all sorts of counters with default options (double values, atomicity full) @@ -42,6 +61,11 @@ struct CounterAlg : Gaudi::Functional::Consumer<void()> { mutable Gaudi::Accumulators::AveragingCounter<unsigned int> avg_int{this, "AverageInteger"}; mutable Gaudi::Accumulators::AveragingCounter<double, Gaudi::Accumulators::atomicity::none> avg_noAto{ this, "AverageNonAtomic"}; + + // test set of counters stored in a deque + mutable int counterCount{0}; + mutable std::deque<Gaudi::Accumulators::Counter<>> counterDeque; + mutable std::mutex counterDequeMutex; }; DECLARE_COMPONENT( CounterAlg ) diff --git a/GaudiExamples/tests/qmtest/refs/CounterAlg.ref b/GaudiExamples/tests/qmtest/refs/CounterAlg.ref index d20e65b734af9f53b7e60dc7ffebe7a39f2d6908..10979551290f9787157638411ee0b820d37a6e99 100644 --- a/GaudiExamples/tests/qmtest/refs/CounterAlg.ref +++ b/GaudiExamples/tests/qmtest/refs/CounterAlg.ref @@ -3,8 +3,8 @@ # <-- End of file '/home/sponce/dev4/Gaudi/GaudiExamples/options/CounterAlg.py' ApplicationMgr SUCCESS ==================================================================================================================================== - Welcome to ApplicationMgr (GaudiCoreSvc v34r0) - running on lblhcbpr11.cern.ch on Mon Aug 10 10:50:10 2020 + Welcome to ApplicationMgr (GaudiCoreSvc v36r1) + running on lblhcbpr11.cern.ch on Tue Oct 5 08:42:36 2021 ==================================================================================================================================== ApplicationMgr INFO Application Manager Configured successfully EventLoopMgr WARNING Unable to locate service "EventSelector" @@ -16,15 +16,26 @@ CounterAlg INFO Super nice message, max 5 times CounterAlg INFO Super nice message, max 5 times CounterAlg INFO Super nice message, max 5 times CounterAlg INFO Suppressing message: 'Super nice message, max 5 times' -CounterAlg INFO Number of counters : 8 - | "CounterAlg/Super nice message, max 5 times" | 500 | - | "CounterAlg/Stat" | 500 | 1750 | 3.5000 | 0.0000 | 3.5000 | 3.5000 | - | "CounterAlg/Sigma" | 500 | 1250 | 2.5000 | 0.0000 | - | "CounterAlg/Binomial" | 500 | 500 |( 100.0000 +- 0.000000)% | - | "CounterAlg/Basic" | 500 | - | "CounterAlg/AverageNonAtomic" | 500 | 750 | 1.5000 | - | "CounterAlg/AverageInteger" | 500 | 500 | 1.0000 | - | "CounterAlg/Average" | 500 | 750 | 1.5000 | +CounterAlg INFO Number of counters : 18 + | Counter | # | sum | mean/eff^* | rms/err^* | min | max | + | "Average" | 500 | 750 | 1.5000 | + | "AverageInteger" | 500 | 500 | 1.0000 | + | "AverageNonAtomic" | 500 | 750 | 1.5000 | + | "Basic" | 500 | + |*"Binomial" | 500 | 500 |( 100.0000 +- 0.000000)% | + | "DQCounter10" | 490 | + | "DQCounter11" | 489 | + | "DQCounter12" | 488 | + | "DQCounter13" | 487 | + | "DQCounter14" | 486 | + | "DQCounter15" | 485 | + | "DQCounter16" | 484 | + | "DQCounter17" | 483 | + | "DQCounter18" | 482 | + | "DQCounter19" | 481 | + | "Sigma" | 500 | 1250 | 2.5000 | 0.0000 | + | "Stat" | 500 | 1750 | 3.5000 | 0.0000 | 3.5000 | 3.5000 | + | "Super nice message, max 5 times" | 500 | ApplicationMgr INFO Application Manager Stopped successfully EventLoopMgr INFO Histograms converted successfully according to request. ApplicationMgr INFO Application Manager Finalized successfully diff --git a/GaudiKernel/include/Gaudi/Accumulators.h b/GaudiKernel/include/Gaudi/Accumulators.h index e133916f84b8c0493d853b63e18ab82eca85b46a..e01767b8a9390d1f1539edb5853c84d5a57a4c30 100644 --- a/GaudiKernel/include/Gaudi/Accumulators.h +++ b/GaudiKernel/include/Gaudi/Accumulators.h @@ -861,6 +861,7 @@ namespace Gaudi::Accumulators { /** * An empty ancester of all counters that provides a buffer method that returns a buffer on itself * Also registers the counter to its owner, with default type "counter" + * Due to this registration, move semantic is disabled. But copy semantic remains. * @see Gaudi::Accumulators for detailed documentation */ template <atomicity Atomicity, template <atomicity Ato, typename... Int> class Accumulator, typename... Args> @@ -876,7 +877,9 @@ namespace Gaudi::Accumulators { BufferableCounter( OWNER* o, std::string const& name ) : BufferableCounter( o, name, "counter" ) {} Buffer<Accumulator, Atomicity, Args...> buffer() { return {*this}; } BufferableCounter( BufferableCounter const& ) = default; + BufferableCounter( BufferableCounter&& ) = delete; BufferableCounter& operator=( BufferableCounter const& ) = default; + BufferableCounter& operator=( BufferableCounter&& ) = delete; ~BufferableCounter() { if ( m_monitoringHub ) { m_monitoringHub->removeEntity( *this ); } } @@ -1130,6 +1133,10 @@ namespace Gaudi::Accumulators { if ( by ) log(); return *this; } + MsgCounter( MsgCounter const& ) = default; + MsgCounter( MsgCounter&& ) = delete; + MsgCounter& operator=( MsgCounter const& ) = default; + MsgCounter& operator=( MsgCounter&& ) = delete; ~MsgCounter() { m_monitoringHub.removeEntity( *this ); } template <typename stream> stream& printImpl( stream& o, bool tableFormat ) const {