Skip to content

Commit 9a3b685

Browse files
authored
Merge pull request #6605 from smoogipoo/fast-decoupled-reference
2 parents cfb0d7b + 44127c5 commit 9a3b685

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

osu.Framework/Development/DebugUtils.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,31 @@
88
using NUnit.Framework;
99
using NUnit.Framework.Internal;
1010
using osu.Framework.Extensions.ObjectExtensions;
11+
using osu.Framework.Platform;
12+
using osu.Framework.Timing;
1113

1214
namespace osu.Framework.Development
1315
{
1416
public static class DebugUtils
1517
{
18+
/// <summary>
19+
/// This represents a clock that runs at a faster-than-realtime pace during unit testing,
20+
/// and is intended to substitute for a <see cref="StopwatchClock"/> that would normally
21+
/// be used to track a realtime reference.
22+
/// </summary>
23+
/// <remarks>
24+
/// <list type="bullet">
25+
/// <item>
26+
/// Components such as <see cref="DecouplingFramedClock"/> use this to advance time at a faster
27+
/// pace in order to not induce artificial delays from having to way on wall clock time to elapse.
28+
/// </item>
29+
/// <item>
30+
/// Note that this property is only populated after the <see cref="GameHost"/> is run.
31+
/// </item>
32+
/// </list>
33+
/// </remarks>
34+
internal static IClock? RealtimeClock { get; set; }
35+
1636
public static bool IsNUnitRunning => is_nunit_running.Value;
1737

1838
private static readonly Lazy<bool> is_nunit_running = new Lazy<bool>(() =>

osu.Framework/Platform/HeadlessGameHost.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.Linq;
88
using osu.Framework.Configuration;
9+
using osu.Framework.Development;
910
using osu.Framework.Graphics.Rendering.Dummy;
1011
using osu.Framework.Input.Handlers;
1112
using osu.Framework.Logging;
@@ -79,7 +80,8 @@ protected override void SetupForRun()
7980

8081
if (!realtime)
8182
{
82-
customClock = new FramedClock(new FastClock(CLOCK_RATE, Threads.ToArray()));
83+
DebugUtils.RealtimeClock = new FastClock(CLOCK_RATE, Threads.ToArray());
84+
customClock = new FramedClock(DebugUtils.RealtimeClock);
8385

8486
// time is incremented per frame, rather than based on the real-world time.
8587
// therefore our goal is to run frames as fast as possible.
@@ -106,6 +108,12 @@ protected override void UpdateFrame()
106108

107109
protected override IEnumerable<InputHandler> CreateAvailableInputHandlers() => Array.Empty<InputHandler>();
108110

111+
protected override void Dispose(bool isDisposing)
112+
{
113+
base.Dispose(isDisposing);
114+
DebugUtils.RealtimeClock = null;
115+
}
116+
109117
private class FastClock : IClock
110118
{
111119
private readonly double increment;
@@ -134,20 +142,23 @@ public double CurrentTime
134142
{
135143
get
136144
{
137-
double realElapsedTime = stopwatch.Elapsed.TotalMilliseconds;
138-
stopwatch.Restart();
139-
140-
if (allThreadsHaveProgressed)
145+
lock (stopwatch)
141146
{
142-
for (int i = 0; i < gameThreads.Length; i++)
143-
gameThreadLastFrames[i] = gameThreads[i].FrameIndex;
147+
double realElapsedTime = stopwatch.Elapsed.TotalMilliseconds;
148+
stopwatch.Restart();
144149

145-
// Increment time at the expedited rate.
146-
return time += increment;
147-
}
150+
if (allThreadsHaveProgressed)
151+
{
152+
for (int i = 0; i < gameThreads.Length; i++)
153+
gameThreadLastFrames[i] = gameThreads[i].FrameIndex;
154+
155+
// Increment time at the expedited rate.
156+
return time += increment;
157+
}
148158

149-
// Fall back to real time to ensure we don't break random tests that expect threads to be running.
150-
return time += realElapsedTime;
159+
// Fall back to real time to ensure we don't break random tests that expect threads to be running.
160+
return time += realElapsedTime;
161+
}
151162
}
152163
}
153164

osu.Framework/Timing/DecouplingFramedClock.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Diagnostics;
6+
using osu.Framework.Development;
67

78
namespace osu.Framework.Timing
89
{
@@ -70,7 +71,7 @@ public sealed class DecouplingFramedClock : ISourceChangeableClock, IAdjustableC
7071
/// <summary>
7172
/// This clock is used when we are decoupling from the source.
7273
/// </summary>
73-
private readonly StopwatchClock realtimeReferenceClock = new StopwatchClock(true);
74+
private readonly IClock realtimeReferenceClock = DebugUtils.RealtimeClock ?? new StopwatchClock(true);
7475

7576
private IAdjustableClock adjustableSourceClock;
7677

0 commit comments

Comments
 (0)