libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_TIMER_H__ 00029 #define MOOST_TIMER_H__ 00030 00031 #include <string> 00032 #include <map> 00033 #include <boost/shared_ptr.hpp> 00034 #include <boost/thread/mutex.hpp> 00035 #include <boost/date_time/posix_time/posix_time.hpp> 00036 00037 namespace moost { 00038 00042 class timer 00043 { 00044 public: 00045 00046 typedef std::vector< std::pair<int, boost::posix_time::ptime> > threshold_times_type; 00047 00048 private: 00049 00050 boost::mutex mutable m_mutex; 00051 std::vector<int> m_times; 00052 std::vector<int>::iterator m_times_p; 00053 std::vector<int>::iterator m_times_end; 00054 int m_min_time; 00055 int m_max_time; 00056 size_t m_count; 00057 00058 boost::posix_time::ptime m_start_time; 00059 00060 int m_max_threshold_time_ms; 00061 00062 00063 threshold_times_type m_threshold_times; 00064 threshold_times_type::iterator m_threshold_times_p; 00065 threshold_times_type::iterator m_threshold_times_end; 00066 00067 public: 00068 00070 class scoped_time 00071 { 00072 private: 00073 timer & m_timer; 00074 bool m_stopped; 00075 boost::posix_time::ptime m_time; 00076 public: 00077 scoped_time(timer & timer_); 00078 ~scoped_time(); 00079 void stop(); 00080 boost::posix_time::ptime get_time() const; 00081 }; 00082 00086 timer(size_t resolution = 4096, int max_threshold_time_ms = (std::numeric_limits<int>::max)(), size_t threshold_resolution = 128); 00087 00089 void time(const boost::posix_time::ptime & start); 00090 00092 int min_time() const; 00093 00095 float avg_time() const; 00096 00098 void avg_stddev_time(float& avg, float& std_dev) const; 00099 00101 int median_time() const; 00102 00104 int max_time() const; 00105 00107 double count_per_second() const; 00108 00110 size_t count() const; 00111 00112 int get_threshold_time() const 00113 { return m_max_threshold_time_ms; } 00114 00116 template<typename ForwardIterator> 00117 void all_times(ForwardIterator out) const 00118 { 00119 boost::mutex::scoped_lock lock(m_mutex); 00120 for (std::vector<int>::const_iterator it = m_times.begin(); it != m_times_end; ++it) 00121 *out++ = *it; 00122 } 00123 00124 threshold_times_type past_threshold_times(int num) const; // will return the last num entries; 00125 00127 void reset(); 00128 }; 00129 00133 class multi_timer 00134 { 00135 private: 00136 00137 size_t m_resolution; 00138 00139 boost::mutex m_mutex; 00140 // map is nice in that inserting doesn't invalidate any other iterators 00141 // we'll take advantage of that by passing timers by ref to their scoped locks 00142 std::map< std::string, boost::shared_ptr< timer > > m_timers; 00143 00144 public: 00145 00146 multi_timer(size_t resolution = 4096) : m_resolution(resolution) {} 00147 00148 typedef std::map< std::string, boost::shared_ptr< timer > >::iterator iterator; 00149 typedef std::map< std::string, boost::shared_ptr< timer > >::const_iterator const_iterator; 00150 00151 class scoped_time : public timer::scoped_time 00152 { 00153 public: 00154 scoped_time( multi_timer & mt, 00155 const std::string & name, 00156 int max_threshold_time_ms = (std::numeric_limits<int>::max)() ) 00157 : timer::scoped_time( mt(name, max_threshold_time_ms) ) {} 00158 }; 00159 00160 class reassignable_scoped_time 00161 { 00162 public: 00163 reassignable_scoped_time( multi_timer & mt, const std::string & name, int max_threshold_time_ms = (std::numeric_limits<int>::max)()); 00164 ~reassignable_scoped_time(); 00165 00166 void reassign(const std::string& name); 00167 void stop(); 00168 void discard(); 00169 boost::posix_time::ptime get_time() const; 00170 00171 private: 00172 00173 multi_timer& m_multi_timer; 00174 boost::shared_ptr<timer> m_timer; 00175 bool m_stopped; 00176 boost::posix_time::ptime m_time; 00177 boost::mutex m_reassign_mutex; 00178 int m_max_threshold_time_ms; 00179 }; 00180 00181 00182 timer & operator[](const std::string & name) 00183 { 00184 boost::mutex::scoped_lock lock(m_mutex); 00185 boost::shared_ptr< timer > & ptimer = m_timers[name]; 00186 if (!ptimer) 00187 ptimer.reset(new timer(m_resolution)); 00188 return *ptimer; 00189 } 00190 00191 timer & operator()(const std::string & name, int max_threshold_time_ms) 00192 { 00193 boost::mutex::scoped_lock lock(m_mutex); 00194 boost::shared_ptr< timer > & ptimer = m_timers[name]; 00195 if (!ptimer) 00196 ptimer.reset(new timer(m_resolution, max_threshold_time_ms)); 00197 return *ptimer; 00198 } 00199 00200 // grab this before iterating over the collection 00201 boost::mutex & mutex() { return m_mutex; } 00202 00203 // iterators: 00204 iterator begin() { return m_timers.begin(); } 00205 iterator end() { return m_timers.end(); } 00206 const_iterator begin() const { return m_timers.begin(); } 00207 const_iterator end() const { return m_timers.end(); } 00208 }; 00209 00210 } // moost 00211 00212 #endif // MOOST_TIMER_H__