diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 2a8178882e..93ba51367a 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -31,7 +31,7 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); beatmap = new AsyncLazy(populateBeatmap); - background = new AsyncLazy(populateBackground); + background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); track = new AsyncLazy(populateTrack); waveform = new AsyncLazy(populateWaveform); } @@ -99,10 +99,11 @@ namespace osu.Game.Beatmaps if (WaveformLoaded) Waveform?.Dispose(); } - public void DisposeTrack() - { - if (TrackLoaded) Track?.Dispose(); - } + /// + /// Eagerly dispose of the audio track associated with this (if any). + /// Accessing track again will load a fresh instance. + /// + public void RecycleTrack() => track.Recycle(); private void applyRateAdjustments(Track t = null) { @@ -114,11 +115,57 @@ namespace osu.Game.Beatmaps mod.ApplyToClock(t); } - public class AsyncLazy : Lazy> + public class AsyncLazy { - public AsyncLazy(Func valueFactory) - : base(() => Task.Run(valueFactory)) + private Lazy> lazy; + private readonly Func valueFactory; + private readonly Func stillValidFunction; + + public AsyncLazy(Func valueFactory, Func stillValidFunction = null) { + this.valueFactory = valueFactory; + this.stillValidFunction = stillValidFunction; + + init(); + } + + public void Recycle() + { + if (!IsValueCreated) return; + + (lazy.Value.Result as IDisposable)?.Dispose(); + + init(); + } + + public bool IsValueCreated + { + get + { + ensureValid(); + return lazy.IsValueCreated; + } + } + + public Task Value + { + get + { + ensureValid(); + return lazy.Value; + } + } + + private void ensureValid() + { + if (!lazy.IsValueCreated || (stillValidFunction?.Invoke(lazy.Value.Result) ?? true)) return; + + init(); + } + + private void init() + { + lazy = new Lazy>(() => Task.Run(valueFactory)); } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 8eaa20f781..0ddff5e5aa 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -154,7 +154,7 @@ namespace osu.Game Debug.Assert(lastBeatmap != null); Debug.Assert(lastBeatmap.Track != null); - lastBeatmap.DisposeTrack(); + lastBeatmap.RecycleTrack(); } Audio.Track.AddItem(b.Track);