mirror of
https://github.com/ppy/osu.git
synced 2025-02-16 00:22:58 +08:00
Fix thread race conditions on pausing close to a fail.
This commit is contained in:
parent
7b240d84da
commit
94bf1d65b6
@ -44,7 +44,7 @@ namespace osu.Game.Screens.Play
|
|||||||
private const double pause_cooldown = 1000;
|
private const double pause_cooldown = 1000;
|
||||||
private double lastPauseActionTime;
|
private double lastPauseActionTime;
|
||||||
|
|
||||||
private bool canPause => Time.Current >= lastPauseActionTime + pause_cooldown;
|
private bool canPause => ValidForResume && !HasFailed && Time.Current >= lastPauseActionTime + pause_cooldown;
|
||||||
|
|
||||||
private IAdjustableClock sourceClock;
|
private IAdjustableClock sourceClock;
|
||||||
private IFrameBasedClock interpolatedSourceClock;
|
private IFrameBasedClock interpolatedSourceClock;
|
||||||
@ -206,11 +206,28 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
if (!canPause && !force) return;
|
if (!canPause && !force) return;
|
||||||
|
|
||||||
|
sourceClock.Stop();
|
||||||
|
|
||||||
|
// the actual pausing is potentially happening on a different thread.
|
||||||
|
// we want to wait for the source clock to stop so we can be sure all components are in a stable state.
|
||||||
|
if (!IsPaused)
|
||||||
|
{
|
||||||
|
Schedule(() => Pause(force));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to do a final check after all of our children have processed up to the paused clock time.
|
||||||
|
// this is to cover cases where, for instance, the player fails in the last processed frame (which would change canPause).
|
||||||
|
// as the scheduler runs before children updates, let's schedule for the next frame.
|
||||||
|
Schedule(() =>
|
||||||
|
{
|
||||||
|
if (!canPause) return;
|
||||||
|
|
||||||
lastPauseActionTime = Time.Current;
|
lastPauseActionTime = Time.Current;
|
||||||
hudOverlay.KeyCounter.IsCounting = false;
|
hudOverlay.KeyCounter.IsCounting = false;
|
||||||
pauseOverlay.Retries = RestartCount;
|
pauseOverlay.Retries = RestartCount;
|
||||||
pauseOverlay.Show();
|
pauseOverlay.Show();
|
||||||
sourceClock.Stop();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resume()
|
public void Resume()
|
||||||
@ -227,11 +244,11 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
var newPlayer = new Player();
|
var newPlayer = new Player();
|
||||||
|
|
||||||
|
ValidForResume = false;
|
||||||
|
|
||||||
LoadComponentAsync(newPlayer, delegate
|
LoadComponentAsync(newPlayer, delegate
|
||||||
{
|
{
|
||||||
newPlayer.RestartCount = RestartCount + 1;
|
newPlayer.RestartCount = RestartCount + 1;
|
||||||
ValidForResume = false;
|
|
||||||
|
|
||||||
if (!Push(newPlayer))
|
if (!Push(newPlayer))
|
||||||
{
|
{
|
||||||
// Error(?)
|
// Error(?)
|
||||||
@ -247,10 +264,11 @@ namespace osu.Game.Screens.Play
|
|||||||
if (scoreProcessor.HasFailed || onCompletionEvent != null)
|
if (scoreProcessor.HasFailed || onCompletionEvent != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ValidForResume = false;
|
||||||
|
|
||||||
Delay(1000);
|
Delay(1000);
|
||||||
onCompletionEvent = Schedule(delegate
|
onCompletionEvent = Schedule(delegate
|
||||||
{
|
{
|
||||||
ValidForResume = false;
|
|
||||||
Push(new Results
|
Push(new Results
|
||||||
{
|
{
|
||||||
Score = scoreProcessor.CreateScore()
|
Score = scoreProcessor.CreateScore()
|
||||||
@ -262,8 +280,6 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
sourceClock.Stop();
|
sourceClock.Stop();
|
||||||
|
|
||||||
Delay(500);
|
|
||||||
|
|
||||||
HasFailed = true;
|
HasFailed = true;
|
||||||
failOverlay.Retries = RestartCount;
|
failOverlay.Retries = RestartCount;
|
||||||
failOverlay.Show();
|
failOverlay.Show();
|
||||||
|
Loading…
Reference in New Issue
Block a user