1 /*=============================================================================
2     Copyright (c) 2005-2007 Hartmut Kaiser
3                   2007, 2009 Tim Blechmann
4 
5     Distributed under the Boost Software License, Version 1.0.
6     (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_HIGH_RESOLUTION_TIMER_HPP)
10 #    define BOOST_HIGH_RESOLUTION_TIMER_HPP
11 
12 #    include <boost/config.hpp>
13 #    include <boost/throw_exception.hpp>
14 
15 #    if _POSIX_C_SOURCE >= 199309L
16 
17 #        include "time.h"
18 
19 #        include <stdexcept>
20 #        include <limits>
21 
22 namespace boost {
23 
24 class high_resolution_timer {
25 public:
high_resolution_timer()26     high_resolution_timer() { restart(); }
27 
restart()28     void restart() {
29         int status = clock_gettime(CLOCK_REALTIME, &start_time);
30 
31         if (status == -1)
32             boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
33     }
34 
elapsed() const35     double elapsed() const // return elapsed time in seconds
36     {
37         struct timespec now;
38 
39         int status = clock_gettime(CLOCK_REALTIME, &now);
40 
41         if (status == -1)
42             boost::throw_exception(std::runtime_error("Couldn't get current time"));
43 
44         struct timespec diff;
45 
46         double ret_sec = double(now.tv_sec - start_time.tv_sec);
47         double ret_nsec = double(now.tv_nsec - start_time.tv_nsec);
48 
49         while (ret_nsec < 0) {
50             ret_sec -= 1.0;
51             ret_nsec += 1e9;
52         }
53 
54         double ret = ret_sec + ret_nsec / 1e9;
55 
56         return ret;
57     }
58 
elapsed_max() const59     double elapsed_max() const // return estimated maximum value for elapsed()
60     {
61         return double((std::numeric_limits<double>::max)());
62     }
63 
elapsed_min() const64     double elapsed_min() const // return minimum value for elapsed()
65     {
66         return 0.0;
67     }
68 
69 private:
70     struct timespec start_time;
71 };
72 
73 } // namespace boost
74 
75 #    elif defined(__APPLE__)
76 
77 #        import <mach/mach_time.h>
78 
79 
80 namespace boost {
81 
82 class high_resolution_timer {
83 public:
high_resolution_timer(void)84     high_resolution_timer(void) {
85         mach_timebase_info_data_t info;
86 
87         kern_return_t err = mach_timebase_info(&info);
88         if (err)
89             throw std::runtime_error("cannot create mach timebase info");
90 
91         conversion_factor = (double)info.numer / (double)info.denom;
92         restart();
93     }
94 
restart()95     void restart() { start = mach_absolute_time(); }
96 
elapsed() const97     double elapsed() const // return elapsed time in seconds
98     {
99         uint64_t now = mach_absolute_time();
100         double duration = double(now - start) * conversion_factor;
101 
102         return duration
103     }
104 
elapsed_max() const105     double elapsed_max() const // return estimated maximum value for elapsed()
106     {
107         return double((std::numeric_limits<double>::max)());
108     }
109 
elapsed_min() const110     double elapsed_min() const // return minimum value for elapsed()
111     {
112         return 0.0;
113     }
114 
115 private:
116     uint64_t start;
117     double conversion_factor;
118 };
119 
120 } // namespace boost
121 
122 #    elif defined(BOOST_WINDOWS)
123 
124 #        include <stdexcept>
125 #        include <limits>
126 #        include <windows.h>
127 
128 namespace boost {
129 
130 ///////////////////////////////////////////////////////////////////////////////
131 //
132 //  high_resolution_timer
133 //      A timer object measures elapsed time.
134 //      CAUTION: Windows only!
135 //
136 ///////////////////////////////////////////////////////////////////////////////
137 class high_resolution_timer {
138 public:
high_resolution_timer()139     high_resolution_timer() {
140         start_time.QuadPart = 0;
141         frequency.QuadPart = 0;
142 
143         if (!QueryPerformanceFrequency(&frequency))
144             boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
145 
146         restart();
147     }
148 
restart()149     void restart() {
150         if (!QueryPerformanceCounter(&start_time))
151             boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
152     }
153 
elapsed() const154     double elapsed() const // return elapsed time in seconds
155     {
156         LARGE_INTEGER now;
157         if (!QueryPerformanceCounter(&now))
158             boost::throw_exception(std::runtime_error("Couldn't get current time"));
159 
160         return double(now.QuadPart - start_time.QuadPart) / frequency.QuadPart;
161     }
162 
elapsed_max() const163     double elapsed_max() const // return estimated maximum value for elapsed()
164     {
165         return (double((std::numeric_limits<LONGLONG>::max)()) - double(start_time.QuadPart))
166             / double(frequency.QuadPart);
167     }
168 
elapsed_min() const169     double elapsed_min() const // return minimum value for elapsed()
170     {
171         return 1.0 / frequency.QuadPart;
172     }
173 
174 private:
175     LARGE_INTEGER start_time;
176     LARGE_INTEGER frequency;
177 };
178 
179 } // namespace boost
180 
181 #    else
182 
183 //  For other platforms, simply fall back to boost::timer
184 #        include <boost/timer.hpp>
185 #        include <boost/throw_exception.hpp>
186 
187 namespace boost {
188 typedef boost::timer high_resolution_timer;
189 }
190 
191 #    endif
192 
193 #endif // !defined(BOOST_HIGH_RESOLUTION_TIMER_HPP)
194