mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 14:15:03 +08:00
Merge pull request #10751 from smoogipoo/fix-bdc-threadsafety
This commit is contained in:
commit
c8917d1236
@ -30,8 +30,22 @@ namespace osu.Game.Beatmaps
|
|||||||
// Too many simultaneous updates can lead to stutters. One thread seems to work fine for song select display purposes.
|
// Too many simultaneous updates can lead to stutters. One thread seems to work fine for song select display purposes.
|
||||||
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.
|
/// <summary>
|
||||||
private readonly LockedWeakList<BindableStarDifficulty> trackedBindables = new LockedWeakList<BindableStarDifficulty>();
|
/// All bindables that should be updated along with the current ruleset + mods.
|
||||||
|
/// </summary>
|
||||||
|
private readonly WeakList<BindableStarDifficulty> trackedBindables = new WeakList<BindableStarDifficulty>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancellation sources used by tracked bindables.
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<CancellationTokenSource> linkedCancellationSources = new List<CancellationTokenSource>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock to be held when operating on <see cref="trackedBindables"/> or <see cref="linkedCancellationSources"/>.
|
||||||
|
/// </summary>
|
||||||
|
private readonly object bindableUpdateLock = new object();
|
||||||
|
|
||||||
|
private CancellationTokenSource trackedUpdateCancellationSource;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmapManager { get; set; }
|
private BeatmapManager beatmapManager { get; set; }
|
||||||
@ -59,7 +73,10 @@ namespace osu.Game.Beatmaps
|
|||||||
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);
|
||||||
trackedBindables.Add(bindable);
|
|
||||||
|
lock (bindableUpdateLock)
|
||||||
|
trackedBindables.Add(bindable);
|
||||||
|
|
||||||
return bindable;
|
return bindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +103,8 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <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;
|
||||||
@ -140,23 +158,23 @@ namespace osu.Game.Beatmaps
|
|||||||
return DifficultyRating.Easy;
|
return DifficultyRating.Easy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CancellationTokenSource trackedUpdateCancellationSource;
|
|
||||||
private readonly List<CancellationTokenSource> linkedCancellationSources = new List<CancellationTokenSource>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 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()
|
||||||
{
|
{
|
||||||
cancelTrackedBindableUpdate();
|
lock (bindableUpdateLock)
|
||||||
trackedUpdateCancellationSource = new CancellationTokenSource();
|
|
||||||
|
|
||||||
foreach (var b in trackedBindables)
|
|
||||||
{
|
{
|
||||||
var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(trackedUpdateCancellationSource.Token, b.CancellationToken);
|
cancelTrackedBindableUpdate();
|
||||||
linkedCancellationSources.Add(linkedSource);
|
trackedUpdateCancellationSource = new CancellationTokenSource();
|
||||||
|
|
||||||
updateBindable(b, currentRuleset.Value, currentMods.Value, linkedSource.Token);
|
foreach (var b in trackedBindables)
|
||||||
|
{
|
||||||
|
var linkedSource = CancellationTokenSource.CreateLinkedTokenSource(trackedUpdateCancellationSource.Token, b.CancellationToken);
|
||||||
|
linkedCancellationSources.Add(linkedSource);
|
||||||
|
|
||||||
|
updateBindable(b, currentRuleset.Value, currentMods.Value, linkedSource.Token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,15 +183,18 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void cancelTrackedBindableUpdate()
|
private void cancelTrackedBindableUpdate()
|
||||||
{
|
{
|
||||||
trackedUpdateCancellationSource?.Cancel();
|
lock (bindableUpdateLock)
|
||||||
trackedUpdateCancellationSource = null;
|
|
||||||
|
|
||||||
if (linkedCancellationSources != null)
|
|
||||||
{
|
{
|
||||||
foreach (var c in linkedCancellationSources)
|
trackedUpdateCancellationSource?.Cancel();
|
||||||
c.Dispose();
|
trackedUpdateCancellationSource = null;
|
||||||
|
|
||||||
linkedCancellationSources.Clear();
|
if (linkedCancellationSources != null)
|
||||||
|
{
|
||||||
|
foreach (var c in linkedCancellationSources)
|
||||||
|
c.Dispose();
|
||||||
|
|
||||||
|
linkedCancellationSources.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user