libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hp_timer.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2004 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "../../../core/exception.hpp"
20 
21 #include <cassert>
22 #include <iomanip>
23 #include <iostream>
24 
25 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
26 
27 /// A class for providing timings in high-performance counter resolution.
28 template <
29  typename Mdl_
30 >
32 public:
35  /// The units are microseconds.
36  typedef long long value_type;
38  static constexpr unsigned long Hz_to_usec=1000000; ///< The frequency is in Hz, so convert to usec.
39 
40  /**
41  In Hz. Set at program start-up, once.
42  */
43  const value_type frequency; ///< In Hz.
44 
45  /**
46  Time when the process started up.
47  */
49 
50  /**
51  Count in usec when the process started up.
52  */
53  const value_type start_up_count; ///< In usec.
54 
55  __stdcall hp_timer();
56 
57  /// Return the current time in a resolution of 1/frequency units.
58  /**
59  Note that this will have a systematic offset according
60 to the properties of GetSystemTimeAsFileTime().
61 
62  \return Time (NOT local time!) in UTC.
63  */
64  const time_utc_t __fastcall current_time() const noexcept(true);
65 
66  /// Convert a value_type in units of 1/frequency to usec.
67  const value_type __fastcall to_usec(const time_utc_t ticks) const noexcept(true);
68 
69  /// The current count in units of 1/frequency.
70  static const value_type __fastcall current_count() noexcept(true);
71 
72  /**
73  \return In Hz.
74  */
75  static const value_type __fastcall get_frequency();
76 
77  /**
78  Implemented using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
79  */
80  friend std::ostream & __fastcall operator<<(std::ostream &o, const time_utc_t &t);
81 
82 private:
83  static const time_utc_t __fastcall get_start_time();
84 
85  void operator=(hp_timer const &)=delete;
86 };
87 
88 template <typename Mdl_>
89 inline const typename hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::value_type
91  const ULARGE_INTEGER ft={
94  };
95  return static_cast<value_type>(static_cast<double>(ft.QuadPart)*Hz_to_usec/frequency);
96 }
97 
98 template <typename Mdl_>
99 inline const typename hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::value_type
103  assert(Finish.QuadPart>=0i64);
104  return static_cast<value_type>(Finish.QuadPart);
105 }
106 
107 template <typename Mdl_>
108 inline const typename hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::time_utc_t
111  assert(cur_ct>=start_up_count);
113  assert(usec_since_start>=0);
118  };
120  const time_utc_t ret={
123  };
124  return ret;
125 }
126 
127 template <typename Mdl_>
128 inline const typename hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::value_type
131  freq.QuadPart=0i64;
133  if (!ret || (freq.QuadPart==0i64)) {
134  throw exception_type(_T("High-performance counter not supported."), info::function(__LINE__,__PRETTY_FUNCTION__,typeid(&hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::get_frequency)), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
135  }
136  return static_cast<value_type>(freq.QuadPart);
137 }
138 
139 template <typename Mdl_>
140 inline const typename hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::time_utc_t
142  time_utc_t tm;
144  return tm;
145 }
146 
147 template <typename Mdl_>
148 inline
153 }
154 
155 template <typename T>
156 inline
157 hp_interval<T>::~hp_interval() noexcept(true) {
158  const typename timer_t::time_utc_t end=timer.current_time();
159  const ULARGE_INTEGER start_ft={
162  };
166  };
170 }
171 
172 } }
173 
174 inline std::ostream &__fastcall
175 operator<<(std::ostream &ss, const SYSTEMTIME &st) {
176  std::ios_base::iostate err=std::ios_base::goodbit;
177  try {
178  const std::ostream::sentry opfx(ss);
179  if (opfx) {
180  ss<<std::setiosflags(std::ios::right)
181  <<std::setfill('0')
182  <<std::setw(2)<<st.wDay<<"/"
183  <<std::setw(2)<<st.wMonth<<"/"
184  <<std::setw(1)<<st.wYear
185  <<","
186  <<std::setw(2)<<st.wHour<<":"
187  <<std::setw(2)<<st.wMinute<<":"
188  <<std::setw(2)<<st.wSecond<<"."
189  <<std::setw(3)<<st.wMilliseconds;
190  }
191  } catch (std::bad_alloc const &) {
192  err|=std::ios_base::badbit;
193  const std::ios_base::iostate exception_mask=ss.exceptions();
194  if ((exception_mask & std::ios_base::failbit)
195  && !(exception_mask & std::ios_base::badbit)) {
196  ss.setstate(err);
197  } else if (exception_mask & std::ios_base::badbit) {
198  try {
199  ss.setstate(err);
200  } catch (std::ios_base::failure const &) {
201  }
202  throw;
203  }
204  } catch (...) {
205  err|=std::ios_base::failbit;
206  const std::ios_base::iostate exception_mask=ss.exceptions();
207  if ((exception_mask & std::ios_base::badbit)
208  && (err & std::ios_base::badbit)) {
209  ss.setstate(err);
210  } else if (exception_mask & std::ios_base::failbit) {
211  try {
212  ss.setstate(err);
213  } catch (std::ios_base::failure const &) {
214  }
215  throw;
216  }
217  }
218  if (err) ss.setstate(err);
219  return ss;
220 }
221 
222 template <typename Mdl_>
223 inline std::ostream & __fastcall
224 operator<<(std::ostream &o, const typename jmmcg::LIBJMMCG_VER_NAMESPACE::hp_timer<ppd::generic_traits::MS_Win32,Mdl_>::time_utc_t &t) {
225  SYSTEMTIME st;
226  if (::FileTimeToSystemTime(&t,&st)) {
227  o<<st;
228  return o;
229  } else {
230  throw hp_timer<generic_traits::MS_Win32,Mdl_>::exception(_T("Failed to convert the input FILETIME to a SYSTEMTIME."), info::function(__LINE__,__PRETTY_FUNCTION__), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
231  }
232 }