1 /* 2 * Copyright (C) 2013-2016 Christoph L. Spiel 3 * 4 * This file is part of Enblend. 5 * 6 * Enblend is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * Enblend is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with Enblend; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 22 #include "timer.h" 23 24 25 namespace timer 26 { 27 inline static double clock_in_seconds(clock_t a_clock_time)28 clock_in_seconds(clock_t a_clock_time) 29 { 30 return static_cast<double>(a_clock_time) / static_cast<double>(CLOCKS_PER_SEC); 31 } 32 33 StandardWallClock()34 StandardWallClock::StandardWallClock() 35 { 36 start(); 37 } 38 39 40 void start()41 StandardWallClock::start() 42 { 43 value_ = clock_t(); 44 start_ = clock(); 45 stop_ = start_; 46 } 47 48 49 void stop()50 StandardWallClock::stop() 51 { 52 stop_ = clock(); 53 value_ += stop_ - start_; 54 start_ = stop_; 55 } 56 57 58 void restart()59 StandardWallClock::restart() 60 { 61 start_ = clock(); 62 stop_ = start_; 63 } 64 65 66 double value() const67 StandardWallClock::value() const 68 { 69 return clock_in_seconds(value_); 70 } 71 72 73 #ifdef HAVE_CLOCK_GETTIME 74 inline static std::uint64_t timespec_in_nano_seconds(const struct timespec & a_timespec)75 timespec_in_nano_seconds(const struct timespec& a_timespec) 76 { 77 return 78 static_cast<std::uint64_t>(a_timespec.tv_sec) * 1000000000UL + 79 static_cast<std::uint64_t>(a_timespec.tv_nsec); 80 } 81 82 RealTimeWallClock()83 RealTimeWallClock::RealTimeWallClock() 84 { 85 start(); 86 } 87 88 89 void start()90 RealTimeWallClock::start() 91 { 92 value_ = value_t(); 93 clock_gettime(CLOCK_REALTIME, &start_); 94 stop_.tv_sec = start_.tv_sec; 95 stop_.tv_nsec = long(); 96 } 97 98 99 void stop()100 RealTimeWallClock::stop() 101 { 102 clock_gettime(CLOCK_REALTIME, &stop_); 103 value_ += timespec_in_nano_seconds(stop_) - timespec_in_nano_seconds(start_); 104 start_ = stop_; 105 } 106 107 108 void restart()109 RealTimeWallClock::restart() 110 { 111 clock_gettime(CLOCK_REALTIME, &start_); 112 stop_ = start_; 113 } 114 115 116 double value() const117 RealTimeWallClock::value() const 118 { 119 return static_cast<double>(value_) * 1e-9; 120 } 121 #endif // HAVE_CLOCK_GETTIME 122 123 124 #ifdef WIN32 125 inline static ULONGLONG filetime_in_100nanoseconds(const _FILETIME & a_filetime)126 filetime_in_100nanoseconds(const _FILETIME& a_filetime) 127 { 128 return 129 (static_cast<ULONGLONG>(a_filetime.dwHighDateTime) << 32) + 130 static_cast<ULONGLONG>(a_filetime.dwLowDateTime); 131 } 132 133 ProcessorTime()134 ProcessorTime::ProcessorTime() 135 { 136 start(); 137 } 138 139 140 void start()141 ProcessorTime::start() 142 { 143 _FILETIME idle; 144 _FILETIME kernel; 145 _FILETIME user; 146 147 user_value_ = ULONGLONG(); 148 system_value_ = ULONGLONG(); 149 150 GetSystemTimes(&idle, &kernel, &user); 151 start_idle_value_ = filetime_in_100nanoseconds(idle); 152 start_system_value_ = filetime_in_100nanoseconds(kernel); 153 start_user_value_ = filetime_in_100nanoseconds(user); 154 } 155 156 157 void stop()158 ProcessorTime::stop() 159 { 160 _FILETIME idle; 161 _FILETIME kernel; 162 _FILETIME user; 163 164 GetSystemTimes(&idle, &kernel, &user); 165 const ULONGLONG stop_idle_value = filetime_in_100nanoseconds(idle); 166 const ULONGLONG stop_system_value = filetime_in_100nanoseconds(kernel); 167 const ULONGLONG stop_user_value = filetime_in_100nanoseconds(user); 168 169 system_value_ = stop_system_value - start_system_value_ - (stop_idle_value - start_idle_value_); 170 user_value_ = stop_user_value - start_user_value_; 171 start_idle_value_ = stop_idle_value; 172 start_system_value_ = stop_system_value; 173 start_user_value_ = stop_user_value; 174 } 175 176 177 void restart()178 ProcessorTime::restart() 179 { 180 _FILETIME idle; 181 _FILETIME kernel; 182 _FILETIME user; 183 184 GetSystemTimes(&idle, &kernel, &user); 185 start_idle_value_ = filetime_in_100nanoseconds(idle); 186 start_system_value_ = filetime_in_100nanoseconds(kernel); 187 start_user_value_ = filetime_in_100nanoseconds(user); 188 } 189 190 191 double value() const192 UserTime::value() const 193 { 194 return user_value_ / 1.0E7; 195 } 196 197 198 double value() const199 SystemTime::value() const 200 { 201 return system_value_ / 1.0E7; 202 } 203 204 #elif defined(HAVE_SYS_TIMES_H) 205 ProcessorTime()206 ProcessorTime::ProcessorTime() 207 { 208 start(); 209 } 210 211 212 void start()213 ProcessorTime::start() 214 { 215 user_value_ = clock_t(); 216 system_value_ = clock_t(); 217 times(&start_); 218 stop_.tms_utime = start_.tms_utime; 219 stop_.tms_stime = start_.tms_stime; 220 } 221 222 223 void stop()224 ProcessorTime::stop() 225 { 226 times(&stop_); 227 user_value_ = stop_.tms_utime - start_.tms_utime; 228 system_value_ = stop_.tms_stime - start_.tms_stime; 229 start_.tms_utime = stop_.tms_utime; 230 start_.tms_stime = stop_.tms_stime; 231 } 232 233 234 void restart()235 ProcessorTime::restart() 236 { 237 times(&start_); 238 stop_.tms_utime = start_.tms_utime; 239 stop_.tms_stime = start_.tms_stime; 240 } 241 242 243 double value() const244 UserTime::value() const 245 { 246 return clock_in_seconds(user_value_); 247 } 248 249 250 double value() const251 SystemTime::value() const 252 { 253 return clock_in_seconds(system_value_); 254 } 255 256 #else 257 258 double value() const259 UserTime::value() const 260 { 261 return 0.0; 262 } 263 264 265 double value() const266 SystemTime::value() const 267 { 268 return 0.0; 269 } 270 #endif 271 } // namespace timer 272