You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.9 KiB
100 lines
2.9 KiB
5 years ago
|
#if NET20 || NET30 || NET35 || !NET_4_6
|
||
|
|
||
|
namespace System.Threading
|
||
|
{
|
||
|
public static class LazyInitializer
|
||
|
{
|
||
|
public static T EnsureInitialized<T>(ref T target)
|
||
|
where T : class
|
||
|
{
|
||
|
var found = target;
|
||
|
Thread.MemoryBarrier();
|
||
|
if (found != null)
|
||
|
{
|
||
|
return found;
|
||
|
}
|
||
|
var value = GetDefaultCtorValue<T>();
|
||
|
if (value == null)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
return Interlocked.CompareExchange(ref target, value, null) ?? value;
|
||
|
}
|
||
|
|
||
|
public static T EnsureInitialized<T>(ref T target, Func<T> valueFactory)
|
||
|
where T : class
|
||
|
{
|
||
|
var found = target;
|
||
|
Thread.MemoryBarrier();
|
||
|
if (found != null)
|
||
|
{
|
||
|
return found;
|
||
|
}
|
||
|
var value = valueFactory();
|
||
|
if (value == null)
|
||
|
{
|
||
|
throw new InvalidOperationException("valueFactory returned null");
|
||
|
}
|
||
|
return Interlocked.CompareExchange(ref target, value, null) ?? value;
|
||
|
}
|
||
|
|
||
|
public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock)
|
||
|
{
|
||
|
if (syncLock == null)
|
||
|
{
|
||
|
Interlocked.CompareExchange(ref syncLock, new object(), null);
|
||
|
}
|
||
|
if (Volatile.Read(ref initialized))
|
||
|
{
|
||
|
return target;
|
||
|
}
|
||
|
lock (syncLock)
|
||
|
{
|
||
|
if (Volatile.Read(ref initialized))
|
||
|
{
|
||
|
return target;
|
||
|
}
|
||
|
target = GetDefaultCtorValue<T>();
|
||
|
Volatile.Write(ref initialized, true);
|
||
|
}
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock, Func<T> valueFactory)
|
||
|
{
|
||
|
if (syncLock == null)
|
||
|
{
|
||
|
Interlocked.CompareExchange(ref syncLock, new object(), null);
|
||
|
}
|
||
|
if (Volatile.Read(ref initialized))
|
||
|
{
|
||
|
return target;
|
||
|
}
|
||
|
lock (syncLock)
|
||
|
{
|
||
|
if (Volatile.Read(ref initialized))
|
||
|
{
|
||
|
return target;
|
||
|
}
|
||
|
target = valueFactory();
|
||
|
Volatile.Write(ref initialized, true);
|
||
|
}
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
private static T GetDefaultCtorValue<T>()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
return Activator.CreateInstance<T>();
|
||
|
}
|
||
|
catch
|
||
|
{
|
||
|
throw new MissingMemberException("The type being lazily initialized does not have a "
|
||
|
+ "public, parameterless constructor.");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|