Last active
August 29, 2015 14:16
-
-
Save neremin/f7311989f5163d01726d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class WeakLazy<T> where T : class | |
{ | |
protected readonly Func<T> valueFactory; | |
internal protected WeakLazy(Func<T> valueFactory) | |
{ | |
Contract.Requires<ArgumentNullException>(valueFactory != null); | |
this.valueFactory = valueFactory; | |
} | |
public abstract T Value { get; } | |
} | |
public sealed class InterlockedWeakLazy<T> : WeakLazy<T> where T: class | |
{ | |
WeakReference<T> reference; | |
public InterlockedWeakLazy(Func<T> valueFactory) | |
: base(valueFactory) | |
{ | |
} | |
public override T Value | |
{ | |
get | |
{ | |
T value; | |
var weakReference = InterlockedFactory.GetOrCreate(ref reference, () => new WeakReference<T>(null)); | |
if (reference.TryGetTarget(out value)) | |
{ | |
return value; | |
} | |
lock (weakReference) | |
{ | |
if (!reference.TryGetTarget(out value)) | |
{ | |
value = valueFactory(); | |
weakReference.SetTarget(value); | |
} | |
} | |
return value; | |
} | |
} | |
} | |
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable")] | |
public sealed class ThreadLocalWeakLazy<T> : WeakLazy<T> where T : class | |
{ | |
readonly ThreadLocal<WeakReference<T>> reference = new ThreadLocal<WeakReference<T>>(() => new WeakReference<T>(null), trackAllValues: false); | |
public ThreadLocalWeakLazy(Func<T> valueFactory) | |
: base(valueFactory) | |
{ | |
} | |
public override T Value | |
{ | |
get | |
{ | |
T value; | |
var weakReference = reference.Value; | |
if (!weakReference.TryGetTarget(out value)) | |
{ | |
value = valueFactory(); | |
weakReference.SetTarget(value); | |
} | |
return value; | |
} | |
} | |
} | |
/// <devdoc> | |
/// Use this class carefully, as it holds value in a ThreadStatic field. | |
/// Generally, it can be used only if value factory returns instances of {T} and not its children to prevent instances interfering. | |
/// </devdoc> | |
public sealed class ThreadStaticWeakLazy<T> : WeakLazy<T> where T : class | |
{ | |
[ThreadStatic] | |
static WeakReference<T> reference; | |
public ThreadStaticWeakLazy(Func<T> valueFactory) | |
: base(valueFactory) | |
{ | |
} | |
public override T Value | |
{ | |
get | |
{ | |
T value; | |
var weakReference = reference ?? (reference = new WeakReference<T>(null)); | |
if (!weakReference.TryGetTarget(out value)) | |
{ | |
value = valueFactory(); | |
Contract.Assert(value != null); | |
Contract.Assert(typeof(T) == value.GetType()); | |
weakReference.SetTarget(value); | |
} | |
return value; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment