LCOV - code coverage report
Current view: top level - DCPS - ThreadStatusManager.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 12 107 11.2 %
Date: 2023-04-30 01:32:43 Functions: 4 9 44.4 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *
       4             :  * Distributed under the OpenDDS License.
       5             :  * See: http://www.opendds.org/license.html
       6             :  */
       7             : 
       8             : #include <DCPS/DdsDcps_pch.h> // Only the _pch include should start with DCPS/
       9             : 
      10             : #include "ThreadStatusManager.h"
      11             : #include "SafetyProfileStreams.h"
      12             : #include "debug.h"
      13             : 
      14             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      15             : 
      16             : namespace OpenDDS {
      17             : namespace DCPS {
      18             : 
      19           0 : void ThreadStatusManager::Thread::update(const MonotonicTimePoint& m_now,
      20             :                                          const SystemTimePoint& s_now,
      21             :                                          ThreadStatus next_status,
      22             :                                          const TimeDuration& bucket_limit,
      23             :                                          bool nested)
      24             : {
      25           0 :   timestamp_ = s_now;
      26             : 
      27           0 :   if (nested) {
      28           0 :     switch(next_status) {
      29           0 :     case ThreadStatus_Active:
      30           0 :       ++nesting_depth_;
      31           0 :       break;
      32           0 :     case ThreadStatus_Idle:
      33           0 :       --nesting_depth_;
      34           0 :       break;
      35             :     }
      36             :   }
      37             : 
      38           0 :   if (!nested ||
      39           0 :       (next_status == ThreadStatus_Active && nesting_depth_ == 1) ||
      40           0 :       (next_status == ThreadStatus_Idle && nesting_depth_ == 0)) {
      41           0 :     if (bucket_[current_bucket_].active_time + bucket_[current_bucket_].idle_time > bucket_limit) {
      42           0 :       current_bucket_ = (current_bucket_ + 1) % bucket_count;
      43           0 :       total_.active_time -= bucket_[current_bucket_].active_time;
      44           0 :       bucket_[current_bucket_].active_time = 0;
      45           0 :       total_.idle_time -= bucket_[current_bucket_].idle_time;
      46           0 :       bucket_[current_bucket_].idle_time = 0;
      47             :     }
      48             : 
      49           0 :     const TimeDuration t = m_now - last_update_;
      50             : 
      51           0 :     switch (status_) {
      52           0 :     case ThreadStatus_Active:
      53           0 :       bucket_[current_bucket_].active_time += t;
      54           0 :       total_.active_time += t;
      55           0 :       break;
      56           0 :     case ThreadStatus_Idle:
      57           0 :       bucket_[current_bucket_].idle_time += t;
      58           0 :       total_.idle_time += t;
      59           0 :       break;
      60             :     }
      61             : 
      62           0 :     last_update_ = m_now;
      63           0 :     status_ = next_status;
      64           0 :   }
      65           0 : }
      66             : 
      67           0 : double ThreadStatusManager::Thread::utilization(const MonotonicTimePoint& now) const
      68             : {
      69           0 :   const TimeDuration active_bonus = (now > last_update_ && status_ == ThreadStatus_Active) ? (now - last_update_) : TimeDuration::zero_value;
      70           0 :   const TimeDuration idle_bonus = (now > last_update_ && status_ == ThreadStatus_Idle) ? (now - last_update_) : TimeDuration::zero_value;
      71           0 :   const TimeDuration denom = total_.active_time + active_bonus + total_.idle_time + idle_bonus;
      72             : 
      73           0 :   if (!denom.is_zero()) {
      74           0 :     return (total_.active_time + active_bonus) / denom;
      75             :   }
      76           0 :   return 0;
      77           0 : }
      78             : 
      79           0 : ThreadStatusManager::ThreadId ThreadStatusManager::get_thread_id()
      80             : {
      81             : #if defined (ACE_WIN32)
      82             :   return static_cast<unsigned>(ACE_Thread::self());
      83             : #else
      84             : #  ifdef ACE_HAS_GETTID
      85           0 :   return ACE_OS::thr_gettid();
      86             : #  else
      87             :   char buffer[32];
      88             :   const size_t len = ACE_OS::thr_id(buffer, 32);
      89             :   return String(buffer, len);
      90             : #  endif
      91             : #endif /* ACE_WIN32 */
      92             : }
      93             : 
      94           9 : void ThreadStatusManager::add_thread(const String& name)
      95             : {
      96           9 :   if (!update_thread_status()) {
      97           9 :     return;
      98             :   }
      99             : 
     100           0 :   const ThreadId thread_id = get_thread_id();
     101             : 
     102           0 :   String bit_key = to_dds_string(thread_id);
     103             : 
     104           0 :   if (name.length()) {
     105           0 :     bit_key += " (" + name + ")";
     106             :   }
     107             : 
     108           0 :   if (DCPS_debug_level > 4) {
     109           0 :     ACE_DEBUG((LM_DEBUG, "(%P|%t) ThreadStatusManager::add_thread: "
     110             :                "adding thread %C\n", bit_key.c_str()));
     111             :   }
     112             : 
     113           0 :   ACE_GUARD(ACE_Thread_Mutex, g, lock_);
     114           0 :   map_.insert(std::make_pair(thread_id, Thread(bit_key)));
     115           0 : }
     116             : 
     117        2752 : void ThreadStatusManager::active(bool nested)
     118             : {
     119        2752 :   if (!update_thread_status()) {
     120        2752 :     return;
     121             :   }
     122             : 
     123           0 :   ACE_GUARD(ACE_Thread_Mutex, g, lock_);
     124             : 
     125           0 :   const MonotonicTimePoint m_now = MonotonicTimePoint::now();
     126           0 :   const SystemTimePoint s_now = SystemTimePoint::now();
     127           0 :   const ThreadId thread_id = get_thread_id();
     128             : 
     129           0 :   const Map::iterator pos = map_.find(thread_id);
     130           0 :   if (pos != map_.end()) {
     131           0 :     pos->second.update(m_now, s_now, Thread::ThreadStatus_Active, bucket_limit_, nested);
     132             :   }
     133             : 
     134           0 :   cleanup(m_now);
     135           0 : }
     136             : 
     137        2752 : void ThreadStatusManager::idle(bool nested)
     138             : {
     139        2752 :   if (!update_thread_status()) {
     140        2752 :     return;
     141             :   }
     142             : 
     143           0 :   ACE_GUARD(ACE_Thread_Mutex, g, lock_);
     144             : 
     145           0 :   const MonotonicTimePoint m_now = MonotonicTimePoint::now();
     146           0 :   const SystemTimePoint s_now = SystemTimePoint::now();
     147           0 :   const ThreadId thread_id = get_thread_id();
     148             : 
     149           0 :   const Map::iterator pos = map_.find(thread_id);
     150           0 :   if (pos != map_.end()) {
     151           0 :     pos->second.update(m_now, s_now, Thread::ThreadStatus_Idle, bucket_limit_, nested);
     152             :   }
     153             : 
     154           0 :   cleanup(m_now);
     155           0 : }
     156             : 
     157           9 : void ThreadStatusManager::finished()
     158             : {
     159           9 :   if (!update_thread_status()) {
     160           9 :     return;
     161             :   }
     162             : 
     163           0 :   ACE_GUARD(ACE_Thread_Mutex, g, lock_);
     164             : 
     165           0 :   const MonotonicTimePoint m_now = MonotonicTimePoint::now();
     166           0 :   const SystemTimePoint s_now = SystemTimePoint::now();
     167           0 :   const ThreadId thread_id = get_thread_id();
     168             : 
     169           0 :   const Map::iterator pos = map_.find(thread_id);
     170           0 :   if (pos != map_.end()) {
     171           0 :     pos->second.update(m_now, s_now, Thread::ThreadStatus_Idle, bucket_limit_, false);
     172             : 
     173           0 :     list_.push_back(pos->second);
     174           0 :     map_.erase(pos);
     175             :   }
     176             : 
     177           0 :   cleanup(m_now);
     178           0 : }
     179             : 
     180           0 : void ThreadStatusManager::harvest(const MonotonicTimePoint& start,
     181             :                                   ThreadStatusManager::List& running,
     182             :                                   ThreadStatusManager::List& finished) const
     183             : {
     184           0 :   ACE_GUARD(ACE_Thread_Mutex, g, lock_);
     185             : 
     186           0 :   for (Map::const_iterator pos = map_.begin(), limit = map_.end(); pos != limit; ++pos) {
     187           0 :     if (pos->second.last_update() > start) {
     188           0 :       running.push_back(pos->second);
     189             :     }
     190             :   }
     191             : 
     192           0 :   for (List::const_iterator pos = list_.begin(), limit = list_.end(); pos != limit; ++pos) {
     193           0 :     if (pos->last_update() > start) {
     194           0 :       finished.push_back(*pos);
     195             :     }
     196             :   }
     197           0 : }
     198             : 
     199           0 : void ThreadStatusManager::cleanup(const MonotonicTimePoint& now)
     200             : {
     201           0 :   const MonotonicTimePoint cutoff = now - 10 * thread_status_interval_;
     202             : 
     203           0 :   while (!list_.empty() && list_.front().last_update() < cutoff) {
     204           0 :     list_.pop_front();
     205             :   }
     206           0 : }
     207             : 
     208             : 
     209             : } // namespace DCPS
     210             : } // namespace OpenDDS
     211             : 
     212             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16