Line data Source code
1 : /* 2 : * 3 : * 4 : * Distributed under the OpenDDS License. 5 : * See: http://www.opendds.org/license.html 6 : */ 7 : 8 : #ifndef OPENDDS_DCPS_THREADSTATUSMANAGER_H 9 : #define OPENDDS_DCPS_THREADSTATUSMANAGER_H 10 : 11 : #include "dcps_export.h" 12 : #include "TimeTypes.h" 13 : 14 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 15 : 16 : namespace OpenDDS { 17 : namespace DCPS { 18 : 19 : class OpenDDS_Dcps_Export ThreadStatusManager { 20 : public: 21 : 22 : #if defined (ACE_WIN32) 23 : typedef unsigned ThreadId; 24 : #else 25 : 26 : # ifdef ACE_HAS_GETTID 27 : typedef pid_t ThreadId; 28 : # else 29 : typedef String ThreadId; 30 : # endif 31 : #endif /* ACE_WIN32 */ 32 : 33 : class OpenDDS_Dcps_Export Thread { 34 : public: 35 : enum ThreadStatus { 36 : ThreadStatus_Active, 37 : ThreadStatus_Idle, 38 : }; 39 : 40 0 : Thread(const String& bit_key) 41 0 : : bit_key_(bit_key) 42 0 : , timestamp_(SystemTimePoint::now()) 43 0 : , status_(ThreadStatus_Active) 44 0 : , last_update_(MonotonicTimePoint::now()) 45 0 : , current_bucket_(0) 46 0 : , nesting_depth_(0) 47 0 : {} 48 : 49 : const String& bit_key() const { return bit_key_; } 50 : const SystemTimePoint& timestamp() const { return timestamp_; } 51 0 : const MonotonicTimePoint& last_update() const { return last_update_; } 52 : 53 : void update(const MonotonicTimePoint& m_now, 54 : const SystemTimePoint& s_now, 55 : ThreadStatus next_status, 56 : const TimeDuration& bucket_limit, 57 : bool nested); 58 : double utilization(const MonotonicTimePoint& now) const; 59 : 60 : static const size_t bucket_count = 8; 61 : 62 : private: 63 : const String bit_key_; 64 : SystemTimePoint timestamp_; 65 : ThreadStatus status_; 66 : 67 : struct OpenDDS_Dcps_Export Bucket { 68 : TimeDuration active_time; 69 : TimeDuration idle_time; 70 : }; 71 : MonotonicTimePoint last_update_; 72 : Bucket total_; 73 : Bucket bucket_[bucket_count]; 74 : size_t current_bucket_; 75 : size_t nesting_depth_; 76 : }; 77 : typedef OPENDDS_MAP(ThreadId, Thread) Map; 78 : typedef OPENDDS_LIST(Thread) List; 79 : 80 0 : void thread_status_interval(const TimeDuration& thread_status_interval) 81 : { 82 0 : thread_status_interval_ = thread_status_interval; 83 0 : bucket_limit_ = thread_status_interval / static_cast<double>(Thread::bucket_count); 84 0 : } 85 : 86 0 : const TimeDuration& thread_status_interval() const 87 : { 88 0 : return thread_status_interval_; 89 : } 90 : 91 5531 : bool update_thread_status() const 92 : { 93 5531 : return thread_status_interval_ > TimeDuration::zero_value; 94 : } 95 : 96 : /// Add the calling thread with the manager. 97 : /// name is for a more human-friendly name that will be appended to the BIT key. 98 : /// Implicitly makes the thread active and finishes the thread on destruction. 99 : class Start { 100 : public: 101 9 : Start(ThreadStatusManager& thread_status_manager, const String& name) 102 9 : : thread_status_manager_(thread_status_manager) 103 : { 104 9 : thread_status_manager_.add_thread(name); 105 9 : } 106 : 107 9 : ~Start() 108 : { 109 9 : thread_status_manager_.finished(); 110 9 : } 111 : 112 : private: 113 : ThreadStatusManager& thread_status_manager_; 114 : }; 115 : 116 : class Event { 117 : public: 118 25 : Event(ThreadStatusManager& thread_status_manager) 119 25 : : thread_status_manager_(thread_status_manager) 120 : { 121 25 : thread_status_manager_.active(true); 122 25 : } 123 : 124 25 : ~Event() 125 : { 126 25 : thread_status_manager_.idle(true); 127 25 : } 128 : 129 : private: 130 : ThreadStatusManager& thread_status_manager_; 131 : }; 132 : 133 : class Sleeper { 134 : public: 135 2727 : Sleeper(ThreadStatusManager& thread_status_manager) 136 2727 : : thread_status_manager_(thread_status_manager) 137 : { 138 2727 : thread_status_manager_.idle(); 139 2727 : } 140 : 141 2727 : ~Sleeper() 142 : { 143 2727 : thread_status_manager_.active(); 144 2727 : } 145 : 146 : private: 147 : ThreadStatusManager& thread_status_manager_; 148 : }; 149 : 150 : /// Copy active and idle threads to running and finished threads to 151 : /// finished. Only threads updated after start are considered. 152 : void harvest(const MonotonicTimePoint& start, 153 : List& running, 154 : List& finished) const; 155 : 156 : #ifdef ACE_HAS_GETTID 157 : static inline pid_t gettid() 158 : { 159 : return syscall(SYS_gettid); 160 : } 161 : #endif 162 : 163 : private: 164 : static ThreadId get_thread_id(); 165 : void add_thread(const String& name); 166 : void active(bool nested = false); 167 : void idle(bool nested = false); 168 : void finished(); 169 : 170 : void cleanup(const MonotonicTimePoint& now); 171 : 172 : TimeDuration thread_status_interval_; 173 : TimeDuration bucket_limit_; 174 : Map map_; 175 : List list_; 176 : 177 : mutable ACE_Thread_Mutex lock_; 178 : }; 179 : 180 : } // namespace DCPS 181 : } // namespace OpenDDS 182 : 183 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 184 : 185 : #endif /* OPENDDS_DCPS_THREADSTATUSMANAGER_H */