mirror of
https://github.com/ppy/osu
synced 2024-12-13 18:37:04 +00:00
Simplify flow of cancellation token
This commit is contained in:
parent
3d59bab7c6
commit
daea13f491
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@ -13,7 +14,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Threading;
|
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
@ -44,10 +44,9 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
private readonly LoadingSpinner loading;
|
private readonly LoadingSpinner loading;
|
||||||
|
|
||||||
private CancellationTokenSource showScoresCancellationSource;
|
private CancellationTokenSource currentFetchCancellationSource;
|
||||||
|
|
||||||
private APIRequest getScoresRequest;
|
private APIRequest fetchScoresRequest;
|
||||||
private ScheduledDelegate getScoresRequestCallback;
|
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private IAPIProvider api { get; set; }
|
private IAPIProvider api { get; set; }
|
||||||
@ -62,7 +61,6 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
protected set
|
protected set
|
||||||
{
|
{
|
||||||
scores = value;
|
scores = value;
|
||||||
|
|
||||||
updateScoresDrawables();
|
updateScoresDrawables();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,9 +175,10 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a fetch/refresh of scores to be displayed.
|
/// Performs a fetch/refresh of scores to be displayed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns>An <see cref="APIRequest"/> responsible for the fetch operation. This will be queued and performed automatically.</returns>
|
/// <returns>An <see cref="APIRequest"/> responsible for the fetch operation. This will be queued and performed automatically.</returns>
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected abstract APIRequest FetchScores();
|
protected abstract APIRequest FetchScores(CancellationToken cancellationToken);
|
||||||
|
|
||||||
protected abstract LeaderboardScore CreateDrawableScore(TScoreInfo model, int index);
|
protected abstract LeaderboardScore CreateDrawableScore(TScoreInfo model, int index);
|
||||||
|
|
||||||
@ -187,37 +186,36 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
private void refetchScores()
|
private void refetchScores()
|
||||||
{
|
{
|
||||||
cancelPendingWork();
|
Reset();
|
||||||
|
|
||||||
PlaceholderState = PlaceholderState.Retrieving;
|
PlaceholderState = PlaceholderState.Retrieving;
|
||||||
loading.Show();
|
loading.Show();
|
||||||
|
|
||||||
getScoresRequest = FetchScores();
|
currentFetchCancellationSource = new CancellationTokenSource();
|
||||||
|
|
||||||
if (getScoresRequest == null)
|
fetchScoresRequest = FetchScores(currentFetchCancellationSource.Token);
|
||||||
|
|
||||||
|
if (fetchScoresRequest == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
getScoresRequest.Failure += e => getScoresRequestCallback = Schedule(() =>
|
fetchScoresRequest.Failure += e => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (e is OperationCanceledException)
|
if (e is OperationCanceledException || currentFetchCancellationSource.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlaceholderState = PlaceholderState.NetworkFailure;
|
PlaceholderState = PlaceholderState.NetworkFailure;
|
||||||
});
|
});
|
||||||
|
|
||||||
api?.Queue(getScoresRequest);
|
api?.Queue(fetchScoresRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelPendingWork()
|
private void cancelPendingWork()
|
||||||
{
|
{
|
||||||
showScoresCancellationSource?.Cancel();
|
currentFetchCancellationSource?.Cancel();
|
||||||
showScoresCancellationSource = null;
|
currentFetchCancellationSource = null;
|
||||||
|
|
||||||
getScoresRequest?.Cancel();
|
fetchScoresRequest?.Cancel();
|
||||||
getScoresRequest = null;
|
fetchScoresRequest = null;
|
||||||
|
|
||||||
getScoresRequestCallback?.Cancel();
|
|
||||||
getScoresRequestCallback = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Placeholder handling
|
#region Placeholder handling
|
||||||
@ -279,8 +277,6 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
scrollFlow?.FadeOut(fade_duration, Easing.OutQuint).Expire();
|
scrollFlow?.FadeOut(fade_duration, Easing.OutQuint).Expire();
|
||||||
scrollFlow = null;
|
scrollFlow = null;
|
||||||
|
|
||||||
showScoresCancellationSource?.Cancel();
|
|
||||||
|
|
||||||
if (scores?.Any() != true)
|
if (scores?.Any() != true)
|
||||||
{
|
{
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
@ -288,6 +284,8 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.Assert(!currentFetchCancellationSource.IsCancellationRequested);
|
||||||
|
|
||||||
// ensure placeholder is hidden when displaying scores
|
// ensure placeholder is hidden when displaying scores
|
||||||
PlaceholderState = PlaceholderState.Successful;
|
PlaceholderState = PlaceholderState.Successful;
|
||||||
|
|
||||||
@ -315,7 +313,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
scrollContainer.ScrollToStart(false);
|
scrollContainer.ScrollToStart(false);
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
}, (showScoresCancellationSource = new CancellationTokenSource()).Token);
|
}, currentFetchCancellationSource.Token);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
private void replacePlaceholder(Placeholder placeholder)
|
private void replacePlaceholder(Placeholder placeholder)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
@ -30,7 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
|||||||
|
|
||||||
protected override bool IsOnlineScope => true;
|
protected override bool IsOnlineScope => true;
|
||||||
|
|
||||||
protected override APIRequest FetchScores()
|
protected override APIRequest FetchScores(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (roomId.Value == null)
|
if (roomId.Value == null)
|
||||||
return null;
|
return null;
|
||||||
@ -39,6 +40,9 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
|||||||
|
|
||||||
req.Success += r =>
|
req.Success += r =>
|
||||||
{
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
return;
|
||||||
|
|
||||||
Scores = r.Leaderboard;
|
Scores = r.Leaderboard;
|
||||||
TopScore = r.UserScore;
|
TopScore = r.UserScore;
|
||||||
};
|
};
|
||||||
|
@ -108,13 +108,8 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local;
|
protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local;
|
||||||
|
|
||||||
private CancellationTokenSource loadCancellationSource;
|
protected override APIRequest FetchScores(CancellationToken cancellationToken)
|
||||||
|
|
||||||
protected override APIRequest FetchScores()
|
|
||||||
{
|
{
|
||||||
loadCancellationSource?.Cancel();
|
|
||||||
loadCancellationSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
var fetchBeatmapInfo = BeatmapInfo;
|
var fetchBeatmapInfo = BeatmapInfo;
|
||||||
|
|
||||||
if (fetchBeatmapInfo == null)
|
if (fetchBeatmapInfo == null)
|
||||||
@ -125,7 +120,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
if (Scope == BeatmapLeaderboardScope.Local)
|
if (Scope == BeatmapLeaderboardScope.Local)
|
||||||
{
|
{
|
||||||
subscribeToLocalScores();
|
subscribeToLocalScores(cancellationToken);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -160,10 +155,10 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
req.Success += r =>
|
req.Success += r =>
|
||||||
{
|
{
|
||||||
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets, fetchBeatmapInfo)).ToArray(), loadCancellationSource.Token)
|
scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets, fetchBeatmapInfo)).ToArray(), cancellationToken)
|
||||||
.ContinueWith(task => Schedule(() =>
|
.ContinueWith(task => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (loadCancellationSource.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Scores = task.GetResultSafely();
|
Scores = task.GetResultSafely();
|
||||||
@ -184,7 +179,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
Action = () => ScoreSelected?.Invoke(model)
|
Action = () => ScoreSelected?.Invoke(model)
|
||||||
};
|
};
|
||||||
|
|
||||||
private void subscribeToLocalScores()
|
private void subscribeToLocalScores(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
scoreSubscription?.Dispose();
|
scoreSubscription?.Dispose();
|
||||||
scoreSubscription = null;
|
scoreSubscription = null;
|
||||||
@ -197,35 +192,35 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
+ $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1"
|
+ $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1"
|
||||||
+ $" AND {nameof(ScoreInfo.DeletePending)} == false"
|
+ $" AND {nameof(ScoreInfo.DeletePending)} == false"
|
||||||
, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged);
|
, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged);
|
||||||
}
|
|
||||||
|
|
||||||
private void localScoresChanged(IRealmCollection<ScoreInfo> sender, ChangeSet changes, Exception exception)
|
void localScoresChanged(IRealmCollection<ScoreInfo> sender, ChangeSet changes, Exception exception)
|
||||||
{
|
|
||||||
if (IsOnlineScope)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var scores = sender.AsEnumerable();
|
|
||||||
|
|
||||||
if (filterMods && !mods.Value.Any())
|
|
||||||
{
|
{
|
||||||
// we need to filter out all scores that have any mods to get all local nomod scores
|
if (IsOnlineScope || cancellationToken.IsCancellationRequested)
|
||||||
scores = scores.Where(s => !s.Mods.Any());
|
return;
|
||||||
}
|
|
||||||
else if (filterMods)
|
|
||||||
{
|
|
||||||
// otherwise find all the scores that have *any* of the currently selected mods (similar to how web applies mod filters)
|
|
||||||
// we're creating and using a string list representation of selected mods so that it can be translated into the DB query itself
|
|
||||||
var selectedMods = mods.Value.Select(m => m.Acronym);
|
|
||||||
scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
|
|
||||||
}
|
|
||||||
|
|
||||||
scores = scores.Detach();
|
var scores = sender.AsEnumerable();
|
||||||
|
|
||||||
scoreManager.OrderByTotalScoreAsync(scores.ToArray(), loadCancellationSource.Token)
|
if (filterMods && !mods.Value.Any())
|
||||||
.ContinueWith(ordered =>
|
{
|
||||||
{
|
// we need to filter out all scores that have any mods to get all local nomod scores
|
||||||
Scores = ordered.GetResultSafely();
|
scores = scores.Where(s => !s.Mods.Any());
|
||||||
}, TaskContinuationOptions.OnlyOnRanToCompletion);
|
}
|
||||||
|
else if (filterMods)
|
||||||
|
{
|
||||||
|
// otherwise find all the scores that have *any* of the currently selected mods (similar to how web applies mod filters)
|
||||||
|
// we're creating and using a string list representation of selected mods so that it can be translated into the DB query itself
|
||||||
|
var selectedMods = mods.Value.Select(m => m.Acronym);
|
||||||
|
scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
|
||||||
|
}
|
||||||
|
|
||||||
|
scores = scores.Detach();
|
||||||
|
|
||||||
|
scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken)
|
||||||
|
.ContinueWith(ordered =>
|
||||||
|
{
|
||||||
|
Scores = ordered.GetResultSafely();
|
||||||
|
}, TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
Loading…
Reference in New Issue
Block a user