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
#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 |