obfuz/Plugins/dnlib/Utils/UserValue.cs

106 lines
2.1 KiB
C#

// dnlib: See LICENSE.txt for more info
using System;
using System.Diagnostics;
using dnlib.Threading;
namespace dnlib.Utils {
/// <summary>
/// Lazily returns the original value if the user hasn't overwritten the value
/// </summary>
/// <typeparam name="TValue">Value type</typeparam>
[DebuggerDisplay("{value}")]
struct UserValue<TValue> {
#if THREAD_SAFE
Lock theLock;
#endif
Func<TValue> readOriginalValue;
TValue value;
bool isUserValue;
bool isValueInitialized;
#if THREAD_SAFE
/// <summary>
/// Sets the lock that protects the data
/// </summary>
public Lock Lock {
set => theLock = value;
}
#endif
/// <summary>
/// Set a delegate instance that will return the original value
/// </summary>
public Func<TValue> ReadOriginalValue {
set => readOriginalValue = value;
}
/// <summary>
/// Gets/sets the value
/// </summary>
/// <remarks>The getter returns the original value if the value hasn't been initialized.</remarks>
public TValue Value {
get {
#if THREAD_SAFE
theLock?.EnterWriteLock(); try {
#endif
if (!isValueInitialized) {
value = readOriginalValue();
readOriginalValue = null;
isValueInitialized = true;
}
return value;
#if THREAD_SAFE
} finally { theLock?.ExitWriteLock(); }
#endif
}
set {
#if THREAD_SAFE
theLock?.EnterWriteLock(); try {
#endif
this.value = value;
readOriginalValue = null;
isUserValue = true;
isValueInitialized = true;
#if THREAD_SAFE
} finally { theLock?.ExitWriteLock(); }
#endif
}
}
/// <summary>
/// Returns <c>true</c> if the value has been initialized
/// </summary>
public bool IsValueInitialized {
#if THREAD_SAFE
get {
theLock?.EnterReadLock();
try {
return isValueInitialized;
}
finally { theLock?.ExitReadLock(); }
}
#else
get => isValueInitialized;
#endif
}
/// <summary>
/// Returns <c>true</c> if the value was set by the user
/// </summary>
public bool IsUserValue {
#if THREAD_SAFE
get {
theLock?.EnterReadLock();
try {
return isUserValue;
}
finally { theLock?.ExitReadLock(); }
}
#else
get => isUserValue;
#endif
}
}
}