libmoost
/home/mhx/git/github/libmoost/include/moost/timer.h
Go to the documentation of this file.
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__