Skip to content

Instantly share code, notes, and snippets.

@neremin
Last active August 29, 2015 14:16
Show Gist options
  • Save neremin/f7311989f5163d01726d to your computer and use it in GitHub Desktop.
Save neremin/f7311989f5163d01726d to your computer and use it in GitHub Desktop.
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