Skip to content

Commit 6dde281

Browse files
committed
Sleep remaining time before tick in the clock, instead of hardcoded duration.
Both to avoid unnecessary work on slow frequencies, but also to sleep less on higher frequencies to avoid clamping.
1 parent d5f220d commit 6dde281

File tree

5 files changed

+25
-17
lines changed

5 files changed

+25
-17
lines changed

src/core/Clock.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ void Core::Clock::mainLoop() {
170170
}
171171
}
172172

173-
timeSource->sleep(100);
173+
else {
174+
// Sleep the remaining time before the next tick
175+
timeSource->sleep(std::floor(frequency - counter));
176+
}
174177
}
175178

176179
if (Utils::debugL1()) {

src/core/TimeSource.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ double Core::TimeSource::delta() {
3232
return delta.count();
3333
}
3434

35-
void Core::TimeSource::sleep(const int microseconds) const {
36-
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
35+
void Core::TimeSource::sleep(const long nanoseconds) const {
36+
std::this_thread::sleep_for(std::chrono::nanoseconds(nanoseconds));
3737
}

src/core/TimeSource.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ namespace Core {
2424
/** Return amount of time in nanoseconds that has passed since last time this method or reset was called. */
2525
virtual double delta();
2626

27-
/** Sleeps the current thread the specified number of microseconds. */
28-
virtual void sleep(int microseconds) const;
27+
/** Sleeps the current thread the specified number of nanoseconds. */
28+
virtual void sleep(long nanoseconds) const;
2929

3030
private:
3131
std::chrono::steady_clock::time_point lastTime;

test/core/ClockTest.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,23 @@ TEST_SUITE("ClockTest") {
4343
clock.setFrequency(1);
4444
clock.singleStep();
4545

46-
// 1 Hz = 1 clock cycle per second
46+
// 1 Hz = 1 clock cycle per second (1 000 000 000 nanoseconds)
4747
// 1 cycle is 2 completed ticks - 1 rising edge (clock tick) and 1 falling edge (inverted clock tick)
48-
// 1 time delta takes 100 ms (0.1s)
49-
// To spend 1 second on this single step, we have to ask for delta and sleep 10 times
48+
// 1 time delta takes 100 ms (0.1s / 100 000 000 ns)
5049

5150
// Clock tick must be the first, and then inverted clock tick
5251
fakeit::Verify(Method(listenerMock, clockTicked), Method(listenerMock, invertedClockTicked)).Once();
52+
53+
// To spend 1 second on this single step, we have to ask for delta 10 times since sleep does nothing
5354
fakeit::Verify(Method(timeSourceMock, delta)).Exactly(10);
54-
fakeit::Verify(Method(timeSourceMock, sleep).Using(100)).Exactly(10);
55+
56+
// It tries to calculate how long to sleep to avoid unnecessary work. In the real world
57+
// it would sleep 400ms if the delta was 100ms, to spend a total of 500ms on a tick.
58+
// In this test it counts down by the delta, since the delta is fixed instead of based on time passed.
59+
fakeit::Verify(Method(timeSourceMock, sleep).Using(400000000),
60+
Method(timeSourceMock, sleep).Using(300000000),
61+
Method(timeSourceMock, sleep).Using(200000000),
62+
Method(timeSourceMock, sleep).Using(100000000)).Twice();
5563
fakeit::Verify(Method(timeSourceMock, reset)).Once();
5664
}
5765

@@ -62,11 +70,11 @@ TEST_SUITE("ClockTest") {
6270

6371
// 2 Hz = 2 clock cycles per second
6472
// 1 time delta takes 10 ms (0.01s)
65-
// To spend 500 ms on this single step, we have to ask for delta and sleep 50 times
73+
// To spend 500 ms on this single step, we have to ask for delta 50 times
6674

6775
fakeit::Verify(Method(listenerMock, clockTicked), Method(listenerMock, invertedClockTicked)).Once();
6876
fakeit::Verify(Method(timeSourceMock, delta)).Exactly(50);
69-
fakeit::Verify(Method(timeSourceMock, sleep)).Exactly(50);
77+
fakeit::Verify(Method(timeSourceMock, sleep)).Exactly(48); // Doesn't sleep when it ticks
7078
fakeit::Verify(Method(timeSourceMock, reset)).Once();
7179
}
7280

@@ -80,7 +88,7 @@ TEST_SUITE("ClockTest") {
8088

8189
fakeit::Verify(Method(listenerMock, clockTicked), Method(listenerMock, invertedClockTicked)).Once();
8290
fakeit::Verify(Method(timeSourceMock, delta)).Twice();
83-
fakeit::Verify(Method(timeSourceMock, sleep)).Twice();
91+
fakeit::Verify(Method(timeSourceMock, sleep)).Never(); // No need to sleep
8492
fakeit::Verify(Method(timeSourceMock, reset)).Once();
8593
}
8694

@@ -94,7 +102,6 @@ TEST_SUITE("ClockTest") {
94102
// Should be 3 times of everything from the previous test
95103
fakeit::Verify(Method(listenerMock, clockTicked), Method(listenerMock, invertedClockTicked)).Exactly(3);
96104
fakeit::Verify(Method(timeSourceMock, delta)).Exactly(6);
97-
fakeit::Verify(Method(timeSourceMock, sleep)).Exactly(6);
98105
fakeit::Verify(Method(timeSourceMock, reset)).Exactly(3);
99106
}
100107

@@ -144,7 +151,6 @@ TEST_SUITE("ClockTest") {
144151

145152
fakeit::VerifyNoOtherInvocations(listenerMock);
146153
fakeit::Verify(Method(timeSourceMock, delta)).Twice();
147-
fakeit::Verify(Method(timeSourceMock, sleep)).Twice();
148154
fakeit::Verify(Method(timeSourceMock, reset)).Once();
149155
}
150156

@@ -164,7 +170,6 @@ TEST_SUITE("ClockTest") {
164170
// This will be many many times since sleep is mocked
165171
fakeit::Verify(Method(listenerMock, clockTicked), Method(listenerMock, invertedClockTicked)).AtLeast(100);
166172
fakeit::Verify(Method(timeSourceMock, delta)).AtLeast(100);
167-
fakeit::Verify(Method(timeSourceMock, sleep)).AtLeast(100);
168173
fakeit::Verify(Method(timeSourceMock, reset)).Exactly(1);
169174
}
170175

test/core/TimeSourceTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ TEST_SUITE("TimeSourceTest") {
1717
double startCount = timeSource.delta();
1818
WARN(startCount < 1000);
1919

20-
timeSource.sleep(100);
20+
timeSource.sleep(microToNano(100));
2121

2222
// Not easy to verify sleep, but should have slept at least 100 microseconds, and at most 200 hopefully
2323
double stopCount = timeSource.delta();
@@ -37,7 +37,7 @@ TEST_SUITE("TimeSourceTest") {
3737
TEST_CASE("reset() should reset delta") {
3838
TimeSource timeSource;
3939

40-
timeSource.sleep(100);
40+
timeSource.sleep(microToNano(100));
4141
timeSource.reset();
4242

4343
double count = timeSource.delta();

0 commit comments

Comments
 (0)