libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
hp_timer.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2008 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 <sys/time.h>
20 #include <cassert>
21 #include <iomanip>
22 #include <iostream>
23 
24 /// Link with -lrt to include these functions.
25 #if _POSIX_C_SOURCE<199309L
26 #error "POSIX clock_*()s required for this library."
27 #endif
28 
29 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
30 
31 template <typename Mdl>
32 class hp_timer<ppd::generic_traits::api_type::posix_pthreads, Mdl> {
33 public:
36  /// The units are microseconds.
37  typedef unsigned long long value_type;
38  typedef timespec time_utc_t;
39 
40  /**
41  Time when the process started up.
42  */
44 
45  /**
46  Count in usec when the process started up.
47  */
48  const value_type start_up_count; ///< In usec.
49 
50  __stdcall hp_timer() noexcept(false) FORCE_INLINE;
51 
52  /// Return the current time in a resolution of 1/frequency units.
53  /**
54  Note that this will have a systematic offset according to the properties of GetSystemTimeAsFileTime().
55 
56  \return Time (NOT local time!) in UTC.
57  */
58  const time_utc_t __fastcall current_time() const noexcept(false) FORCE_INLINE;
59 
60  /// Convert a value_type in units of 1/frequency to usec.
61  static value_type __fastcall to_usec(const time_utc_t ticks) noexcept(true) FORCE_INLINE;
62 
63  /// The current count in units of 1/frequency.
64  static value_type __fastcall current_count() noexcept(false) FORCE_INLINE;
65 
66  /**
67  Implemented using the advice given in "Standard C++ IOStreams and Locales" by A.Langer & K.Kreft, page 170.
68  */
69  friend std::ostream & __fastcall operator<<(std::ostream &o, const time_utc_t &t);
70 
71 private:
72  static const time_utc_t __fastcall get_start_time() noexcept(false) FORCE_INLINE;
73 };
74 
75 inline tostream &__fastcall
76 operator<<(tostream &ss, const timespec &st) {
77  std::ios_base::iostate err=std::ios_base::goodbit;
78  try {
79  const tostream::sentry opfx(ss);
80  if (opfx) {
81  ss<<st.tv_sec<<_T(".")
82  <<st.tv_nsec;
83  }
84  } catch (std::bad_alloc const &) {
85  err|=std::ios_base::badbit;
86  const std::ios_base::iostate exception_mask=ss.exceptions();
87  if ((exception_mask & std::ios_base::failbit)
88  && !(exception_mask & std::ios_base::badbit)) {
89  ss.setstate(err);
90  } else if (exception_mask & std::ios_base::badbit) {
91  try {
92  ss.setstate(err);
93  } catch (std::ios_base::failure const &) {
94  }
95  throw;
96  }
97  } catch (...) {
98  err|=std::ios_base::failbit;
99  const std::ios_base::iostate exception_mask=ss.exceptions();
100  if ((exception_mask & std::ios_base::badbit)
101  && (err & std::ios_base::badbit)) {
102  ss.setstate(err);
103  } else if (exception_mask & std::ios_base::failbit) {
104  try {
105  ss.setstate(err);
106  } catch (std::ios_base::failure const &) {
107  }
108  throw;
109  }
110  }
111  if (err) ss.setstate(err);
112  return ss;
113 }
114 
115 } }
116 
117 #include "hp_timer_impl.hpp"