// dnlib: See LICENSE.txt for more info
using System;
using System.Diagnostics;
using System.Threading;
using dnlib.DotNet;
namespace dnlib.Utils {
///
/// A readonly list that gets initialized lazily
///
/// Any class type
[DebuggerDisplay("Count = {Length}")]
sealed class SimpleLazyList where T : class {
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
readonly T[] elements;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
readonly Func readElementByRID;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
readonly uint length;
///
/// Gets the length of this list
///
public uint Length => length;
///
/// Access the list
///
/// Index
/// The element or null if is invalid
public T this[uint index] {
get {
if (index >= length)
return null;
if (elements[index] is null)
Interlocked.CompareExchange(ref elements[index], readElementByRID(index + 1), null);
return elements[index];
}
}
///
/// Constructor
///
/// Length of the list
/// Delegate instance that lazily reads an element. It might
/// be called more than once for each rid in rare cases. It must never return
/// null.
public SimpleLazyList(uint length, Func readElementByRID) {
this.length = length;
this.readElementByRID = readElementByRID;
elements = new T[length];
}
}
///
/// A readonly list that gets initialized lazily
///
/// Any class type
[DebuggerDisplay("Count = {Length}")]
sealed class SimpleLazyList2 where T : class, IContainsGenericParameter2 {
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
readonly T[] elements;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
readonly Func readElementByRID;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
readonly uint length;
///
/// Gets the length of this list
///
public uint Length => length;
///
/// Access the list
///
/// Index
/// Generic parameter context
/// The element or null if is invalid
public T this[uint index, GenericParamContext gpContext] {
get {
if (index >= length)
return null;
if (elements[index] is null) {
var elem = readElementByRID(index + 1, gpContext);
// Don't cache it if it contains GPs since each GP could hold a reference
// to the type/method context. These GPs can't be shared.
if (elem.ContainsGenericParameter)
return elem;
Interlocked.CompareExchange(ref elements[index], elem, null);
}
return elements[index];
}
}
///
/// Constructor
///
/// Length of the list
/// Delegate instance that lazily reads an element. It might
/// be called more than once for each rid. It must never return null.
public SimpleLazyList2(uint length, Func readElementByRID) {
this.length = length;
this.readElementByRID = readElementByRID;
elements = new T[length];
}
}
}