liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//  This code is based on Timer and Chrono code. Thanks to authors:
//
//  Boost.Timer:
//  Copyright Beman Dawes 1994-2007, 2011
//
//  Boost.Chrono:
//  Copyright Beman Dawes 2008
//  Copyright 2009-2010 Vicente J. Botet Escriba
//
//  Simplified and modified to be able to support exceptionless (-fno-exceptions).
//  Boost.Timer depends on Boost.Chorno wich uses boost::throw_exception.
//  And Boost.Chrono DLLs don't build in Win32 as there is no 
//  boost::throw_exception(std::exception const&) implementation
//  in Boost.Chrono:
//
//  Copyright 2020 Ion Gaztanaga
//
//  Distributed under the Boost Software License, Version 1.0.
//  See http://www.boost.org/LICENSE_1_0.txt
 
//----------------------------------------------------------------------------//
//                                Windows                                     //
//----------------------------------------------------------------------------//
#ifndef BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
#define BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP
 
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/cstdlib.hpp>
 
 
#   if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
#     define BOOST_MOVE_DETAIL_WINDOWS_API
#   elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#     define BOOST_MOVE_DETAIL_MAC_API
#   else
#     define BOOST_MOVE_DETAIL_POSIX_API
#   endif
 
#if defined(BOOST_MOVE_DETAIL_WINDOWS_API)
 
#include <boost/winapi/time.hpp>
#include <boost/winapi/timers.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/assert.hpp>
#include <boost/core/ignore_unused.hpp>
 
namespace boost { namespace move_detail {
 
template<int Dummy>
struct QPFHolder
{
   static inline double get_nsec_per_tic()
   {
      boost::winapi::LARGE_INTEGER_ freq;
      boost::winapi::BOOL_ r = boost::winapi::QueryPerformanceFrequency( &freq );
      boost::ignore_unused(r);
      BOOST_ASSERT(r != 0 && "Boost::Move - get_nanosecs_per_tic Internal Error");
 
      return double(1000000000.0L / freq.QuadPart);
   }
 
   static const double nanosecs_per_tic;
};
 
template<int Dummy>
const double QPFHolder<Dummy>::nanosecs_per_tic = get_nsec_per_tic();
 
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
   double nanosecs_per_tic = QPFHolder<0>::nanosecs_per_tic;
   
   boost::winapi::LARGE_INTEGER_ pcount;
   unsigned times=0;
   while ( !boost::winapi::QueryPerformanceCounter( &pcount ) )
   {
      if ( ++times > 3 )
      {
         BOOST_ASSERT("Boost::Move - QueryPerformanceCounter Internal Error");
         return 0u;
      }
   }
 
   return static_cast<boost::uint64_t>((nanosecs_per_tic) * pcount.QuadPart);
}
 
}}  //namespace boost { namespace move_detail {
 
#elif defined(BOOST_MOVE_DETAIL_MAC_API)
 
#include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
 
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
   boost::uint64_t count = ::mach_absolute_time();
 
   mach_timebase_info_data_t info;
   mach_timebase_info(&info);
   return static_cast<boost::uint64_t>
      (  static_cast<double>(count)*(static_cast<double>(info.numer) / info.denom);
}
 
#elif defined(BOOST_MOVE_DETAIL_POSIX_API)
 
#include <time.h>
 
#  if defined(CLOCK_MONOTONIC_PRECISE)   //BSD
#     define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
#  elif defined(CLOCK_MONOTONIC_RAW)     //Linux
#     define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
#  elif defined(CLOCK_HIGHRES)           //Solaris
#     define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_HIGHRES
#  elif defined(CLOCK_MONOTONIC)         //POSIX (AIX, BSD, Linux, Solaris)
#     define BOOST_MOVE_DETAIL_CLOCK_MONOTONIC CLOCK_MONOTONIC
#  else
#     error "No high resolution steady clock in your system, please provide a patch"
#  endif
 
inline boost::uint64_t nsec_clock() BOOST_NOEXCEPT
{
   struct timespec count;
   ::clock_gettime(BOOST_MOVE_DETAIL_CLOCK_MONOTONIC, &count);
   boost::uint64_t r = count.tv_sec;
   r *= 1000000000U;
   r += count.tv_nsec;
   return r;
}
 
#endif  // POSIX
 
namespace boost { namespace move_detail {
 
typedef boost::uint64_t nanosecond_type;
 
struct cpu_times
{
   nanosecond_type wall;
   nanosecond_type user;
   nanosecond_type system;
 
   void clear() { wall = user = system = 0; }
};
 
 
inline void get_cpu_times(boost::move_detail::cpu_times& current)
{
    current.wall = nsec_clock();
}
 
 
class cpu_timer
{
   public:
 
      //  constructor
      cpu_timer() BOOST_NOEXCEPT                                   { start(); }
 
      //  observers
      bool          is_stopped() const BOOST_NOEXCEPT              { return m_is_stopped; }
      cpu_times     elapsed() const BOOST_NOEXCEPT;  // does not stop()
 
      //  actions
      void          start() BOOST_NOEXCEPT;
      void          stop() BOOST_NOEXCEPT;
      void          resume() BOOST_NOEXCEPT; 
 
   private:
      cpu_times     m_times;
      bool          m_is_stopped;
};
 
 
//  cpu_timer  ---------------------------------------------------------------------//
 
inline void cpu_timer::start() BOOST_NOEXCEPT
{
   m_is_stopped = false;
   get_cpu_times(m_times);
}
 
inline void cpu_timer::stop() BOOST_NOEXCEPT
{
   if (is_stopped())
      return;
   m_is_stopped = true;
      
   cpu_times current;
   get_cpu_times(current);
   m_times.wall = (current.wall - m_times.wall);
   m_times.user = (current.user - m_times.user);
   m_times.system = (current.system - m_times.system);
}
 
inline cpu_times cpu_timer::elapsed() const BOOST_NOEXCEPT
{
   if (is_stopped())
      return m_times;
   cpu_times current;
   get_cpu_times(current);
   current.wall -= m_times.wall;
   current.user -= m_times.user;
   current.system -= m_times.system;
   return current;
}
 
inline void cpu_timer::resume() BOOST_NOEXCEPT
{
   if (is_stopped())
   {
      cpu_times current (m_times);
      start();
      m_times.wall   -= current.wall;
      m_times.user   -= current.user;
      m_times.system -= current.system;
   }
}
 
 
 
}  // namespace move_detail
}  // namespace boost
 
#endif   //BOOST_MOVE_DETAIL_NSEC_CLOCK_HPP