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