class some_performer_t { ... void work_started() { std::lock_guard< activity_tracking::lock_t > lock{ m_stats_lock }; m_is_in_working = true; m_work_started_at = activity_tracking::clock_type_t::now(); m_work_activity.m_count += 1; } void work_finished() { std::lock_guard< activity_tracking::lock_t > lock{ m_stats_lock }; m_is_in_working = false; activity_tracking::update_stats_from_current_time( m_work_activity, m_work_started_at ); } activity_tracking::stats_t take_work_stats() { activity_tracking::stats_t result; bool is_in_working{ false }; activity_tracking::clock_type_t::time_point work_started_at; { std::lock_guard< activity_tracking::lock_t > lock{ m_stats_lock }; result = m_work_activity; if( true == (is_in_working = m_is_in_working) ) work_started_at = m_work_started_at; } if( is_in_working ) activity_tracking::update_stats_from_current_time( result, work_started_at ); return result; } ... activity_tracking::lock_t m_stats_lock; bool m_is_in_working; activity_tracking::clock_type_t::time_point m_work_started_at; activity_tracking::stats_t m_work_activity; ... }; class some_performer_t { ... void work_started() { m_work_stats.start(); } void work_finished() { m_work_stats.stop(); } activity_tracking::stats_t take_work_stats() { return m_work_stats.take_stats(); } ... activity_tracking::stats_collector_t m_work_stats; ... }; class stats_collector_t { public : void start() { /* work_started */ } void stop() { /* work_finished */ } stats_t take_stats() { /* take_work_stats */ } private : lock_t m_lock; bool m_is_in_working{ false }; clock_type_t::time_point m_work_started_at; stats_t m_work_activity{}; }; template< LOCK_HOLDER > class stats_collector_t { public : // , // - LOCK_HOLDER-. // // LOCK_HOLDER, stats_collector_t. template< typename... ARGS > stats_collector_t( ARGS && ...args ) : m_lock_holder{ std::forward<ARGS>(args)... } {} void start() { std::lock_guard< LOCK_HOLDER > lock{ m_lock_holder }; ... /* */ } void stop() { std::lock_guard< LOCK_HOLDER > lock{ m_lock_holder }; ... /* */ } stats_t take_stats() {...} private : LOCK_HOLDER m_lock_holder; bool m_is_in_working{ false }; clock_type_t::time_point m_work_started_at; stats_t m_work_activity{}; }; class internal_lock_t { lock_t m_lock; public : internal_lock_t() {} void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } }; class external_lock_t { lock_t & m_lock; public : external_lock_t( lock_t & lock ) : m_lock( lock ) {} void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } }; using namespace activity_tracking; class one_performer_t { ... private : // , lock-. lock_t m_common_lock; stats_collector_t< external_lock_t > m_work_stats{ m_common_lock }; stats_collector_t< external_lock_t > m_wait_stats{ m_common_lock }; ... }; class another_performer_t { ... private : // , lock-. stats_collector_t< internal_lock_t > m_work_stats{}; ... }; template< typename LOCK = lock_t > class external_lock_t { LOCK & m_lock; public : external_lock_t( LOCK & lock ) : m_lock( lock ) {} void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } }; using namespace activity_tracking; class one_performer_t { ... private : // , lock-. lock_t m_common_lock; stats_collector_t< external_lock_t<> > m_work_stats{ m_common_lock }; stats_collector_t< external_lock_t<> > m_wait_stats{ m_common_lock }; ... }; class tricky_performer_t { ... private : // , lock- // - . mpmc_queue_traits::lock_t m_common_lock; stats_collector_t< external_lock_t< mpmc_queue_traits::lock_t > > m_work_stats{ m_common_lock }; stats_collector_t< external_lock_t< mpmc_queue_traits::lock_t > > m_wait_stats{ m_common_lock }; ... }; template< typename LOCK_HOLDER > class stats_collector_t { using start_stop_lock_t = typename LOCK_HOLDER::start_stop_lock_t; using take_stats_lock_t = typename LOCK_HOLDER::take_stats_lock_t; public : ... void start() { start_stop_lock_t lock{ m_lock_holder }; ... } void stop() { start_stop_lock_t lock{ m_lock_holder }; ... } stats_t take_stats() { ... { take_stats_lock_t lock{ m_lock_holder }; ... } ... } ... }; class internal_lock_t { lock_t m_lock; public : using start_stop_lock_t = std::lock_guard< internal_lock_t >; using take_stats_lock_t = std::lock_guard< internal_lock_t >; internal_lock_t() {} void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } }; template< typename LOCK_TYPE = lock_t, template<class> class LOCK_POLICY = default_lock_policy_t > class external_lock_t { LOCK_TYPE & m_lock; public : using start_stop_lock_t = typename LOCK_POLICY< external_lock_t >::start_stop_lock_t; using take_stats_lock_t = typename LOCK_POLICY< external_lock_t >::take_stats_lock_t; external_lock_t( LOCK_TYPE & lock ) : m_lock( lock ) {} void lock() { m_lock.lock(); } void unlock() { m_lock.unlock(); } }; template< typename L > struct no_actual_lock_t { no_actual_lock_t( L & ) {} /* */ }; template< typename LOCK_HOLDER > struct default_lock_policy_t { using start_stop_lock_t = std::lock_guard< LOCK_HOLDER >; using take_stats_lock_t = std::lock_guard< LOCK_HOLDER >; }; template< typename LOCK_HOLDER > struct no_lock_at_start_stop_policy_t { using start_stop_lock_t = no_actual_lock_t< LOCK_HOLDER >; using take_stats_lock_t = std::lock_guard< LOCK_HOLDER >; } using namespace activity_tracking; class one_performer_t { ... private : // , lock-. lock_t m_common_lock; stats_collector_t< external_lock_t<> > m_work_stats{ m_common_lock }; stats_collector_t< external_lock_t<> > m_wait_stats{ m_common_lock }; ... }; class tricky_performer_t { ... private : // , lock- // - . mpmc_queue_traits::lock_t m_common_lock; stats_collector_t< external_lock_t< mpmc_queue_traits::lock_t > > m_work_stats{ m_common_lock }; stats_collector_t< external_lock_t< mpmc_queue_traits::lock_t > > m_wait_stats{ m_common_lock }; ... }; class very_tricky_performer_t { ... private : // , lock- // - , // start() stop() . complex_task_queue_t::lock_t m_common_lock; stats_collector_t< external_lock_t< complex_task_queue_t::lock_t, no_lock_at_start_stop_policy_t > > m_wait_stats{ m_common_lock }; ... }; Source: https://habr.com/ru/post/308594/
All Articles