-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathElapsedTimeWithPause.cpp
More file actions
107 lines (96 loc) · 3.39 KB
/
Copy pathElapsedTimeWithPause.cpp
File metadata and controls
107 lines (96 loc) · 3.39 KB
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
/*
* Copyright (C) 2024: Arizona Board of Regents on Behalf of the University of Arizona
*/
#include <thread>
#include <atomic>
#include "ElapsedTimeWithPause.h"
using namespace asdp;
ElapsedTimeWithPause::ElapsedTimeWithPause()
{
Reset();
}
void ElapsedTimeWithPause::Pause()
{
std::shared_ptr<State> oldState = std::atomic_load(&m_state);
std::shared_ptr<State> newState = std::make_shared<State>();
*newState = *oldState; // Make a copy of the current state.
if (!newState->is_paused) {
newState->is_paused = true;
newState->pause_start_time = std::chrono::steady_clock::now();
}
std::atomic_store(&m_state, newState);
}
void ElapsedTimeWithPause::Resume()
{
std::shared_ptr<State> oldState = std::atomic_load(&m_state);
std::shared_ptr<State> newState = std::make_shared<State>();
*newState = *oldState; // Make a copy of the current state.
if (newState->is_paused) {
newState->is_paused = false;
newState->total_pause_time += std::chrono::steady_clock::now() - newState->pause_start_time;
}
std::atomic_store(&m_state, newState);
}
void ElapsedTimeWithPause::Reset()
{
std::shared_ptr<State> newState = std::make_shared<State>();
newState->start_time = std::chrono::steady_clock::now();
newState->total_pause_time = std::chrono::duration<double>::zero();
newState->is_paused = false;
std::atomic_store(&m_state, newState);
}
double ElapsedTimeWithPause::ElapsedTime() const
{
// Make a local copy of the state to avoid having its contents be changed non-atomically by another thread.
std::shared_ptr<State> local_state = std::atomic_load(&m_state);
std::chrono::time_point<std::chrono::steady_clock> now;
if (local_state->is_paused) {
now = local_state->pause_start_time;
} else {
now = std::chrono::steady_clock::now();
}
std::chrono::duration<double> elapsed_time = now - local_state->start_time - local_state->total_pause_time;
return elapsed_time.count();
}
std::string ElapsedTimeWithPause::Test()
{
// Construct an object of the class and make sure its initial time is near zero and it counts up
// over time.
ElapsedTimeWithPause et;
double t0 = et.ElapsedTime();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
double t1 = et.ElapsedTime();
if (t0 > 1e-3) {
return "Error: Initial elapsed time should be near zero.";
}
if (t1 <= t0) {
return "Error: Elapsed time should be increasing.";
}
// Pause the timer and make sure it stops counting up.
et.Pause();
double t2 = et.ElapsedTime();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
double t3 = et.ElapsedTime();
if (t2 != t3) {
return "Error: Elapsed time should not change when paused.";
}
// Resume the timer and make sure it starts counting up again.
et.Resume();
double t4 = et.ElapsedTime();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
double t5 = et.ElapsedTime();
if (t4 > t5) {
return "Error: Elapsed time should be increasing after resuming.";
}
if (t4 < t3) {
return "Error: Resume time should be at least as large as pause time.";
}
// Reset the timer and make sure it starts counting up from zero again.
et.Reset();
double t6 = et.ElapsedTime();
if (t6 > 1e-3) {
return "Error: Elapsed time should be near zero after resetting.";
}
// Everything worked.
return "";
}