Fix potential thread-safety issue

This commit is contained in:
Dean Herbert 2018-09-06 13:27:53 +09:00
parent 8d9e0ff1c3
commit 89a92ab7eb

View File

@ -199,7 +199,7 @@ namespace osu.Game.Beatmaps
private readonly Func<T> valueFactory; private readonly Func<T> valueFactory;
private readonly Func<T, bool> stillValidFunction; private readonly Func<T, bool> stillValidFunction;
private readonly object initLock = new object(); private readonly object fetchLock = new object();
public RecyclableLazy(Func<T> valueFactory, Func<T, bool> stillValidFunction = null) public RecyclableLazy(Func<T> valueFactory, Func<T, bool> stillValidFunction = null)
{ {
@ -223,29 +223,17 @@ namespace osu.Game.Beatmaps
{ {
get get
{ {
recreateIfInvalid(); lock (fetchLock)
return lazy.Value; {
if (!stillValid)
recreate();
return lazy.Value;
}
} }
} }
private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true); private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true);
private void recreateIfInvalid()
{
lock (initLock)
{
if (!lazy.IsValueCreated)
// we have not yet been initialised or haven't run the task.
return;
if (stillValid)
// we are still in a valid state.
return;
recreate();
}
}
private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication); private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
} }
} }