mirror of https://github.com/ppy/osu
Fix unsafe list manipulation in BeatmapDifficultyCache
This commit is contained in:
parent
d7c30f9b42
commit
66ea1572c7
|
@ -31,7 +31,7 @@ public class BeatmapDifficultyCache : MemoryCachingComponent<BeatmapDifficultyCa
|
||||||
private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(1, nameof(BeatmapDifficultyCache));
|
private readonly ThreadedTaskScheduler updateScheduler = new ThreadedTaskScheduler(1, nameof(BeatmapDifficultyCache));
|
||||||
|
|
||||||
// All bindables that should be updated along with the current ruleset + mods.
|
// All bindables that should be updated along with the current ruleset + mods.
|
||||||
private readonly LockedWeakList<BindableStarDifficulty> trackedBindables = new LockedWeakList<BindableStarDifficulty>();
|
private readonly WeakList<BindableStarDifficulty> trackedBindables = new WeakList<BindableStarDifficulty>();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmapManager { get; set; }
|
private BeatmapManager beatmapManager { get; set; }
|
||||||
|
@ -59,7 +59,10 @@ protected override void LoadComplete()
|
||||||
public IBindable<StarDifficulty> GetBindableDifficulty([NotNull] BeatmapInfo beatmapInfo, CancellationToken cancellationToken = default)
|
public IBindable<StarDifficulty> GetBindableDifficulty([NotNull] BeatmapInfo beatmapInfo, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var bindable = createBindable(beatmapInfo, currentRuleset.Value, currentMods.Value, cancellationToken);
|
var bindable = createBindable(beatmapInfo, currentRuleset.Value, currentMods.Value, cancellationToken);
|
||||||
|
|
||||||
|
lock (trackedBindables)
|
||||||
trackedBindables.Add(bindable);
|
trackedBindables.Add(bindable);
|
||||||
|
|
||||||
return bindable;
|
return bindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +89,8 @@ public IBindable<StarDifficulty> GetBindableDifficulty([NotNull] BeatmapInfo bea
|
||||||
/// <param name="mods">The <see cref="Mod"/>s to get the difficulty with.</param>
|
/// <param name="mods">The <see cref="Mod"/>s to get the difficulty with.</param>
|
||||||
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops computing the star difficulty.</param>
|
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops computing the star difficulty.</param>
|
||||||
/// <returns>The <see cref="StarDifficulty"/>.</returns>
|
/// <returns>The <see cref="StarDifficulty"/>.</returns>
|
||||||
public Task<StarDifficulty> GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null, [CanBeNull] IEnumerable<Mod> mods = null, CancellationToken cancellationToken = default)
|
public Task<StarDifficulty> GetDifficultyAsync([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo rulesetInfo = null, [CanBeNull] IEnumerable<Mod> mods = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
// In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset.
|
// In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset.
|
||||||
rulesetInfo ??= beatmapInfo.Ruleset;
|
rulesetInfo ??= beatmapInfo.Ruleset;
|
||||||
|
@ -147,6 +151,8 @@ public static DifficultyRating GetDifficultyRating(double starRating)
|
||||||
/// Updates all tracked <see cref="BindableStarDifficulty"/> using the current ruleset and mods.
|
/// Updates all tracked <see cref="BindableStarDifficulty"/> using the current ruleset and mods.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void updateTrackedBindables()
|
private void updateTrackedBindables()
|
||||||
|
{
|
||||||
|
lock (trackedBindables)
|
||||||
{
|
{
|
||||||
cancelTrackedBindableUpdate();
|
cancelTrackedBindableUpdate();
|
||||||
trackedUpdateCancellationSource = new CancellationTokenSource();
|
trackedUpdateCancellationSource = new CancellationTokenSource();
|
||||||
|
@ -159,11 +165,14 @@ private void updateTrackedBindables()
|
||||||
updateBindable(b, currentRuleset.Value, currentMods.Value, linkedSource.Token);
|
updateBindable(b, currentRuleset.Value, currentMods.Value, linkedSource.Token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cancels the existing update of all tracked <see cref="BindableStarDifficulty"/> via <see cref="updateTrackedBindables"/>.
|
/// Cancels the existing update of all tracked <see cref="BindableStarDifficulty"/> via <see cref="updateTrackedBindables"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void cancelTrackedBindableUpdate()
|
private void cancelTrackedBindableUpdate()
|
||||||
|
{
|
||||||
|
lock (trackedBindables)
|
||||||
{
|
{
|
||||||
trackedUpdateCancellationSource?.Cancel();
|
trackedUpdateCancellationSource?.Cancel();
|
||||||
trackedUpdateCancellationSource = null;
|
trackedUpdateCancellationSource = null;
|
||||||
|
@ -176,6 +185,7 @@ private void cancelTrackedBindableUpdate()
|
||||||
linkedCancellationSources.Clear();
|
linkedCancellationSources.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="BindableStarDifficulty"/> and triggers an initial value update.
|
/// Creates a new <see cref="BindableStarDifficulty"/> and triggers an initial value update.
|
||||||
|
|
Loading…
Reference in New Issue