1 /**
2 ** Copyright (C) 2006 – 2018 by Diether Knof
3 **
4 ** This program is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU General Public License as
6 ** published by the Free Software Foundation; either version 2 of
7 ** the License, or (at your option) any later version.
8 **
9 ** This program 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
12 ** GNU General Public License for more details.
13 ** You can find this license in the file 'gpl.txt'.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 ** MA 02111-1307 USA
19 **
20 ** Contact:
21 ** Diether Knof dknof@posteo.de
22 **/
23
24 #include "stop_watch.h"
25
26 #include <iostream>
27 using namespace std;
28
29 /** constructor
30 ** starts the stop watch
31 **/
StartStopProxy(StopWatch & stop_watch)32 StopWatch::StartStopProxy::StartStopProxy(StopWatch& stop_watch) :
33 stop_watch(&stop_watch)
34 { this->stop_watch->start(); }
35
36 /** destructor
37 ** stops the stop watch
38 **/
~StartStopProxy()39 StopWatch::StartStopProxy::~StartStopProxy()
40 { this->stop_watch->stop(); }
41
42 /** -> result
43 **
44 ** @param start_time start time
45 **
46 ** @return difference from 'start_time' to 'now'
47 ** '0' on error
48 **/
49 MSecCounter
diff_to_now(clock_t const start_time)50 StopWatch::diff_to_now(clock_t const start_time) {
51 clock_t const stop_time = clock();
52 if (stop_time == static_cast<clock_t>(-1)) {
53 cerr << "StopWatch::diff_to_now()\n"
54 << " could not get time"
55 << endl;
56 return 0;
57 }
58
59 if (start_time > stop_time) {
60 cerr << "StopWatch::diff_to_now()\n"
61 << " overflow: "
62 << "start time = " << start_time
63 << " > " << stop_time << " = stop time"
64 << endl;
65 return 0;
66 }
67
68 // under Microsoft Windows 'CLOCKS_PER_SEC' is 1000,
69 // under GNU/Linux (Posix) 1000000,
70 // under FreeBSD < 1000
71 // So in order to do integer calculation we have to split the code
72
73 // The variable is needed because 'CLOCKS_PER_SEC' need not to be a
74 // constant (so no '#if CLOCKS_PER_SEC < 1000' can be used).
75 // But with a constant in FreeBSD 'CLOCKS_PER_SEC / 1000' equals 0,
76 // this leads to the warning division with zero (g++-3.4.4).
77 clock_t clocks_per_sec = CLOCKS_PER_SEC;
78 if (clocks_per_sec < 1000) {
79 return ((stop_time - start_time) * (1000 / clocks_per_sec));
80 } else {
81 return ((stop_time - start_time) / (clocks_per_sec / 1000));
82 }
83 } // static MSecCounter StopWatch::diff_to_now(clock_t start_time)
84
85
86 /** constructor
87 **/
StopWatch()88 StopWatch::StopWatch() :
89 start_time(static_cast<clock_t>(-1))
90 { }
91
92 /** destructor
93 **/
~StopWatch()94 StopWatch::~StopWatch()
95 {
96 #ifdef DKNOF
97 if (this->depth > 0) {
98 cerr << "StopWatch::~StopWatch()\n"
99 << " depth is not 0: " << this->depth
100 << endl;
101 #ifndef RELEASE
102 abort();
103 #endif
104 }
105 #endif
106 } // StopWatch::~StopWatch()
107
108 /** @return a start stop proxy
109 **/
110 std::unique_ptr<StopWatch::StartStopProxy>
start_stop_proxy()111 StopWatch::start_stop_proxy()
112 { return std::make_unique<StartStopProxy>(*this); }
113
114 /** start the time counter
115 **/
116 void
start()117 StopWatch::start()
118 {
119 if (this->depth == 0)
120 this->start_time = clock();
121
122 if (this->start_time == static_cast<clock_t>(-1)) {
123 cerr << "StopWatch::start()\n"
124 << " clock could not be started"
125 << endl;
126 return ;
127 }
128
129 this->depth += 1;
130 this->calls_ += 1;
131 } // void StopWatch::start()
132
133 /** stop the time counter
134 **/
135 void
stop()136 StopWatch::stop()
137 {
138 if ( (this->start_time == static_cast<clock_t>(-1))
139 || (this->depth == 0) ) {
140 #ifdef DKNOF
141 cerr << "StopWatch::stop()\n"
142 << "clock not started"
143 << endl;
144 #ifndef RELEASE
145 // (*reinterpret_cast<int*>(NULL) = 0);
146 #endif
147 #endif
148 return ;
149 }
150
151 this->depth -= 1;
152
153 if (this->depth == 0) {
154 this->msec_ += StopWatch::diff_to_now(this->start_time);
155
156 this->start_time = static_cast<clock_t>(-1);
157 }
158 } // void StopWatch::stop()
159
160 /** reset the counter
161 **/
162 void
reset()163 StopWatch::reset()
164 {
165 this->start_time = static_cast<clock_t>(-1);
166 this->msec_ = 0;
167 this->depth = 0;
168 } // void StopWatch::reset()
169
170 /** @return whether the stop watch is running
171 **/
172 bool
running() const173 StopWatch::running() const
174 {
175 return (this->start_time != static_cast<clock_t>(-1));
176 } // bool StopWatch::running() const
177
178 /** @return the stopped time in miliseconds
179 **/
180 MSecCounter
msec() const181 StopWatch::msec() const
182 {
183 if (this->start_time != static_cast<clock_t>(-1))
184 return this->msec_ + StopWatch::diff_to_now(this->start_time);
185 else
186 return this->msec_;
187 } // MSecCounter StopWatch::msec() const
188
189 /** @return how many calls (of start) has been made
190 **/
191 int
calls() const192 StopWatch::calls() const
193 {
194 return this->calls_;
195 } // int StopWatch::calls() const
196