using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.Collections;
namespace Convention.Collections
{
namespace Generic
{
///
/// 附带有缓存机制的链表类
///
/// 指定链表的元素类型
public sealed class LinkedCacheList : ICollection, IEnumerable, ICollection, IEnumerable
{
private readonly LinkedList m_LinkedList;
///
/// 之所以需要这套缓存机制,主要有三点好处:
/// 减少 GC 压力:大量频繁的插入/删除会产生很多短生命周期的节点对象,通过复用可以显著降低托管堆的分配与回收次数
/// 提升性能:避免频繁 new 和 GC,能减少停顿时间,提高链表在高频操作场景下的吞吐
/// 便于观察与管理:类中还提供了 CachedNodeCount 方便调试统计缓存规模,必要时可通过 ClearCachedNodes 主动释放
/// 适用场景是节点使用模式“高频增删但总量有限”,此时缓存能稳定性能;若链表规模始终在增长且很少释放,缓存收益会较低。
///
private readonly Queue> m_CachedNodes;
///
/// 初始化游戏框架链表类的新实例
///
public LinkedCacheList()
{
m_LinkedList = new LinkedList();
m_CachedNodes = new Queue>();
}
///
/// 获取链表中实际包含的结点数量
///
public int Count
{
get
{
return m_LinkedList.Count;
}
}
///
/// 获取链表结点缓存数量
///
public int CachedNodeCount
{
get
{
return m_CachedNodes.Count;
}
}
///
/// 获取链表的第一个结点
///
public LinkedListNode First
{
get
{
return m_LinkedList.First;
}
}
///
/// 获取链表的最后一个结点
///
public LinkedListNode Last
{
get
{
return m_LinkedList.Last;
}
}
///
/// 获取一个值,该值指示 是否为只读
///
public bool IsReadOnly
{
get
{
return ((ICollection)m_LinkedList).IsReadOnly;
}
}
///
/// 获取可用于同步对 的访问的对象。
///
public object SyncRoot
{
get
{
return ((ICollection)m_LinkedList).SyncRoot;
}
}
///
/// 获取一个值,该值指示是否同步对 的访问(线程安全)。
///
public bool IsSynchronized
{
get
{
return ((ICollection)m_LinkedList).IsSynchronized;
}
}
///
/// 在链表中指定的现有结点后添加包含指定值的新结点
///
/// 指定的现有结点
/// 指定值
/// 包含指定值的新结点
public LinkedListNode AddAfter(LinkedListNode node, T value)
{
LinkedListNode newNode = AcquireNode(value);
m_LinkedList.AddAfter(node, newNode);
return newNode;
}
///
/// 在链表中指定的现有结点后添加指定的新结点
///
/// 指定的现有结点
/// 指定的新结点
public void AddAfter(LinkedListNode node, LinkedListNode newNode)
{
m_LinkedList.AddAfter(node, newNode);
}
///
/// 在链表中指定的现有结点前添加包含指定值的新结点
///
/// 指定的现有结点
/// 指定值
/// 包含指定值的新结点
public LinkedListNode AddBefore(LinkedListNode node, T value)
{
LinkedListNode newNode = AcquireNode(value);
m_LinkedList.AddBefore(node, newNode);
return newNode;
}
///
/// 在链表中指定的现有结点前添加指定的新结点
///
/// 指定的现有结点
/// 指定的新结点
public void AddBefore(LinkedListNode node, LinkedListNode newNode)
{
m_LinkedList.AddBefore(node, newNode);
}
///
/// 在链表的开头处添加包含指定值的新结点
///
/// 指定值
/// 包含指定值的新结点
public LinkedListNode AddFirst(T value)
{
LinkedListNode node = AcquireNode(value);
m_LinkedList.AddFirst(node);
return node;
}
///
/// 在链表的开头处添加指定的新结点
///
/// 指定的新结点
public void AddFirst(LinkedListNode node)
{
m_LinkedList.AddFirst(node);
}
///
/// 在链表的结尾处添加包含指定值的新结点
///
/// 指定值
/// 包含指定值的新结点
public LinkedListNode AddLast(T value)
{
LinkedListNode node = AcquireNode(value);
m_LinkedList.AddLast(node);
return node;
}
///
/// 在链表的结尾处添加指定的新结点
///
/// 指定的新结点
public void AddLast(LinkedListNode node)
{
m_LinkedList.AddLast(node);
}
///
/// 从链表中移除所有结点
///
public void Clear()
{
LinkedListNode current = m_LinkedList.First;
while (current != null)
{
ReleaseNode(current);
current = current.Next;
}
m_LinkedList.Clear();
}
///
/// 清除链表结点缓存
///
public void ClearCachedNodes()
{
m_CachedNodes.Clear();
}
///
/// 确定某值是否在链表中
///
/// 指定值
/// 某值是否在链表中
public bool Contains(T value)
{
return m_LinkedList.Contains(value);
}
///
/// 从目标数组的指定索引处开始将整个链表复制到兼容的一维数组
///
/// 一维数组,它是从链表复制的元素的目标。数组必须具有从零开始的索引
/// array 中从零开始的索引,从此处开始复制
public void CopyTo(T[] array, int index)
{
m_LinkedList.CopyTo(array, index);
}
///
/// 从特定的 ICollection 索引开始,将数组的元素复制到一个数组中
///
/// 一维数组,它是从 ICollection 复制的元素的目标。数组必须具有从零开始的索引
/// array 中从零开始的索引,从此处开始复制
public void CopyTo(Array array, int index)
{
((ICollection)m_LinkedList).CopyTo(array, index);
}
///
/// 查找包含指定值的第一个结点
///
/// 要查找的指定值
/// 包含指定值的第一个结点
public LinkedListNode Find(T value)
{
return m_LinkedList.Find(value);
}
///
/// 查找包含指定值的最后一个结点
///
/// 要查找的指定值
/// 包含指定值的最后一个结点
public LinkedListNode FindLast(T value)
{
return m_LinkedList.FindLast(value);
}
///
/// 从链表中移除指定值的第一个匹配项
///
/// 指定值
/// 是否移除成功
public bool Remove(T value)
{
LinkedListNode node = m_LinkedList.Find(value);
if (node != null)
{
m_LinkedList.Remove(node);
ReleaseNode(node);
return true;
}
return false;
}
///
/// 从链表中移除指定的结点
///
/// 指定的结点
public void Remove(LinkedListNode node)
{
m_LinkedList.Remove(node);
ReleaseNode(node);
}
///
/// 移除位于链表开头处的结点
///
public void RemoveFirst()
{
LinkedListNode first = m_LinkedList.First;
if (first == null)
{
throw new InvalidOperationException("Rmove first is invalid.");
}
m_LinkedList.RemoveFirst();
ReleaseNode(first);
}
///
/// 移除位于链表结尾处的结点。
///
public void RemoveLast()
{
LinkedListNode last = m_LinkedList.Last;
if (last == null)
{
throw new InvalidOperationException("Remove last is invalid.");
}
m_LinkedList.RemoveLast();
ReleaseNode(last);
}
///
/// 返回循环访问集合的枚举数
///
/// 循环访问集合的枚举数
public Enumerator GetEnumerator()
{
return new Enumerator(m_LinkedList);
}
private LinkedListNode AcquireNode(T value)
{
LinkedListNode node = null;
if (m_CachedNodes.Count > 0)
{
node = m_CachedNodes.Dequeue();
node.Value = value;
}
else
{
node = new LinkedListNode(value);
}
return node;
}
private void ReleaseNode(LinkedListNode node)
{
node.Value = default(T);
m_CachedNodes.Enqueue(node);
}
///
/// 将值添加到 ICollection`1 的结尾处
///
/// 要添加的值
void ICollection.Add(T value)
{
AddLast(value);
}
///
/// 返回循环访问集合的枚举数
///
/// 循环访问集合的枚举数
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// 返回循环访问集合的枚举数
///
/// 循环访问集合的枚举数
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// 循环访问集合的枚举数
///
[StructLayout(LayoutKind.Auto)]
public struct Enumerator : IEnumerator, IEnumerator
{
private LinkedList.Enumerator m_Enumerator;
internal Enumerator(LinkedList linkedList)
{
if (linkedList == null)
{
throw new InvalidOperationException("Linked list is invalid.");
}
m_Enumerator = linkedList.GetEnumerator();
}
///
/// 获取当前结点
///
public T Current
{
get
{
return m_Enumerator.Current;
}
}
///
/// 获取当前的枚举数
///
object IEnumerator.Current
{
get
{
return m_Enumerator.Current;
}
}
///
/// 清理枚举数
///
public void Dispose()
{
m_Enumerator.Dispose();
}
///
/// 获取下一个结点
///
/// 返回下一个结点
public bool MoveNext()
{
return m_Enumerator.MoveNext();
}
///
/// 重置枚举数
///
void IEnumerator.Reset()
{
((IEnumerator)m_Enumerator).Reset();
}
}
}
}
namespace Cache
{
///
/// Native LRUCache - 基于Unity.Collections的高性能最近最少使用缓存
/// Burst兼容,需要手动Dispose
///
/// 键类型(必须是unmanaged类型)
/// 值类型(必须是unmanaged类型)
public struct NativeLRUCache : IDisposable
where TKey : unmanaged, IEquatable
where TValue : unmanaged
{
// 链表节点
private struct Node
{
public TKey key;
public TValue value;
public int prevIndex; // 前一个节点索引
public int nextIndex; // 后一个节点索引
}
private NativeList nodes; // 节点池
private readonly NativeHashMap hashMap; // key -> 节点索引
private readonly NativeList freeList; // 空闲节点索引池
private readonly int capacity;
private int headIndex; // 链表头(最久未使用)
private int tailIndex; // 链表尾(最近使用)
private int count;
// 是否为有效节点索引
private readonly bool IsValidIndex(int index) => index >= 0;
public NativeLRUCache(int capacity, Allocator allocator)
{
this.capacity = capacity;
this.count = 0;
this.headIndex = -1;
this.tailIndex = -1;
hashMap = new NativeHashMap(capacity, allocator);
nodes = new NativeList(capacity, allocator);
freeList = new NativeList(capacity, allocator);
// 预分配节点池
nodes.Length = capacity;
for (int i = capacity - 1; i >= 0; i--)
{
freeList.Add(i);
}
}
///
/// 获取缓存值
///
public bool TryGetValue(TKey key, out TValue value)
{
if (hashMap.TryGetValue(key, out int nodeIndex))
{
MoveToTail(nodeIndex); // 移动到尾部(最近使用)
value = nodes[nodeIndex].value;
return true;
}
value = default;
return false;
}
///
/// 添加或更新缓存
///
public void Put(TKey key, TValue value)
{
// 已存在则更新并移动到尾部
if (hashMap.TryGetValue(key, out int nodeIndex))
{
Node node = nodes[nodeIndex];
node.value = value;
nodes[nodeIndex] = node;
MoveToTail(nodeIndex);
return;
}
// 容量已满,淘汰头部节点
if (count >= capacity)
{
EvictHead();
}
// 创建新节点
nodeIndex = AllocateNode();
nodes[nodeIndex] = new Node
{
key = key,
value = value,
prevIndex = tailIndex,
nextIndex = -1
};
hashMap.Add(key, nodeIndex);
AddToTail(nodeIndex);
count++;
}
///
/// 删除缓存项
///
public bool Remove(TKey key)
{
if (!hashMap.TryGetValue(key, out int nodeIndex))
return false;
hashMap.Remove(key);
RemoveFromList(nodeIndex);
FreeNode(nodeIndex);
count--;
return true;
}
///
/// 清空缓存
///
public void Clear()
{
hashMap.Clear();
// 重置所有节点到空闲列表
freeList.Clear();
for (int i = 0; i < capacity; i++)
{
freeList.Add(i);
}
headIndex = -1;
tailIndex = -1;
count = 0;
}
// 分配节点索引
private readonly int AllocateNode()
{
int index = freeList[^1];
freeList.RemoveAtSwapBack(freeList.Length - 1);
return index;
}
// 释放节点索引
private readonly void FreeNode(int index)
{
freeList.Add(index);
}
// 将节点移动到链表尾部(标记为最近使用)
private void MoveToTail(int nodeIndex)
{
if (nodeIndex == tailIndex)
return;
RemoveFromList(nodeIndex);
AddToTail(nodeIndex);
}
// 将节点添加到尾部
private void AddToTail(int nodeIndex)
{
Node node = nodes[nodeIndex];
node.prevIndex = tailIndex;
node.nextIndex = -1;
nodes[nodeIndex] = node;
if (IsValidIndex(tailIndex))
{
Node tail = nodes[tailIndex];
tail.nextIndex = nodeIndex;
nodes[tailIndex] = tail;
}
tailIndex = nodeIndex;
// 如果链表为空,头尾指向同一节点
if (!IsValidIndex(headIndex))
{
headIndex = nodeIndex;
}
}
// 从链表中移除节点
private void RemoveFromList(int nodeIndex)
{
Node node = nodes[nodeIndex];
// 更新前一个节点的next指针
if (IsValidIndex(node.prevIndex))
{
Node prev = nodes[node.prevIndex];
prev.nextIndex = node.nextIndex;
nodes[node.prevIndex] = prev;
}
else
{
// 没有前一个节点,说明是头节点
headIndex = node.nextIndex;
}
// 更新后一个节点的prev指针
if (IsValidIndex(node.nextIndex))
{
Node next = nodes[node.nextIndex];
next.prevIndex = node.prevIndex;
nodes[node.nextIndex] = next;
}
else
{
// 没有后一个节点,说明是尾节点
tailIndex = node.prevIndex;
}
}
// 淘汰头部节点(最久未使用)
private void EvictHead()
{
if (!IsValidIndex(headIndex)) return;
int oldHead = headIndex;
Node headNode = nodes[oldHead];
hashMap.Remove(headNode.key);
headIndex = headNode.nextIndex;
if (IsValidIndex(headIndex))
{
Node newHead = nodes[headIndex];
newHead.prevIndex = -1;
nodes[headIndex] = newHead;
}
else
{
tailIndex = -1; // 链表为空
}
FreeNode(oldHead);
count--;
}
public void Dispose()
{
if (hashMap.IsCreated) hashMap.Dispose();
if (nodes.IsCreated) nodes.Dispose();
if (freeList.IsCreated) freeList.Dispose();
headIndex = -1;
tailIndex = -1;
count = 0;
}
// 属性访问器
public readonly int Count => count;
public readonly int Capacity => capacity;
public readonly bool IsCreated => hashMap.IsCreated;
}
///
/// Native LFUCache - 基于Unity.Collections的高性能最不频繁使用缓存
/// Burst兼容,需要手动Dispose
///
/// 键类型(必须是unmanaged类型)
/// 值类型(必须是unmanaged类型)
public struct NativeLFUCache : IDisposable
where TKey : unmanaged, IEquatable
where TValue : unmanaged
{
// 缓存节点
private struct Node
{
public TKey key;
public TValue value;
public int frequency; // 访问频率
public int prevIndex; // 同频率链表中的前一个节点
public int nextIndex; // 同频率链表中的后一个节点
}
// 频率链表头尾
private struct FrequencyList
{
public int headIndex; // 该频率链表的头节点(最久未使用)
public int tailIndex; // 该频率链表的尾节点(最近使用)
public readonly bool IsEmpty => headIndex == -1;
}
private readonly NativeHashMap keyToNodeIndex; // key -> nodeIndex
private NativeList nodes; // 节点池
private readonly NativeList freeList; // 空闲节点索引
private NativeHashMap freqToList; // frequency -> FrequencyList
private readonly int capacity;
private int count;
private int minFrequency; // 当前最小频率
public NativeLFUCache(int capacity, Allocator allocator)
{
this.capacity = capacity;
this.count = 0;
this.minFrequency = 0;
keyToNodeIndex = new NativeHashMap(capacity, allocator);
nodes = new NativeList(capacity, allocator);
freeList = new NativeList(capacity, allocator);
freqToList = new NativeHashMap(capacity, allocator);
// 预分配节点池
nodes.Length = capacity;
for (int i = capacity - 1; i >= 0; i--)
{
freeList.Add(i);
}
}
///
/// 获取缓存值并增加频率
///
public bool TryGetValue(TKey key, out TValue value)
{
if (keyToNodeIndex.TryGetValue(key, out int nodeIndex))
{
// 增加访问频率
IncreaseFrequency(nodeIndex);
value = nodes[nodeIndex].value;
return true;
}
value = default;
return false;
}
///
/// 添加或更新缓存
///
public void Put(TKey key, TValue value)
{
// 更新现有值
if (keyToNodeIndex.TryGetValue(key, out int nodeIndex))
{
Node node = nodes[nodeIndex];
node.value = value;
nodes[nodeIndex] = node;
IncreaseFrequency(nodeIndex);
return;
}
// 容量已满,淘汰最小频率的节点
if (count >= capacity)
{
EvictMinFrequencyNode();
}
// 创建新节点,初始频率为1
nodeIndex = AllocateNode();
nodes[nodeIndex] = new Node
{
key = key,
value = value,
frequency = 1,
prevIndex = -1,
nextIndex = -1
};
keyToNodeIndex.Add(key, nodeIndex);
AddToFrequencyList(nodeIndex, 1);
// 更新最小频率
if (minFrequency == 0)
{
minFrequency = 1;
}
count++;
}
///
/// 删除缓存项
///
public bool Remove(TKey key)
{
if (!keyToNodeIndex.TryGetValue(key, out int nodeIndex))
return false;
RemoveNode(nodeIndex);
return true;
}
///
/// 清空缓存
///
public void Clear()
{
keyToNodeIndex.Clear();
freqToList.Clear();
// 重置所有节点到空闲列表
freeList.Clear();
for (int i = 0; i < capacity; i++)
{
freeList.Add(i);
}
minFrequency = 0;
count = 0;
}
///
/// 释放所有内存
///
public void Dispose()
{
if (keyToNodeIndex.IsCreated) keyToNodeIndex.Dispose();
if (nodes.IsCreated) nodes.Dispose();
if (freeList.IsCreated) freeList.Dispose();
if (freqToList.IsCreated) freqToList.Dispose();
minFrequency = 0;
count = 0;
}
#region 内部辅助方法
private int AllocateNode()
{
int index = freeList[^1];
freeList.RemoveAtSwapBack(freeList.Length - 1);
return index;
}
private void FreeNode(int index)
{
freeList.Add(index);
}
///
/// 增加节点的访问频率
///
private void IncreaseFrequency(int nodeIndex)
{
Node node = nodes[nodeIndex];
int oldFreq = node.frequency;
int newFreq = oldFreq + 1;
// 从旧频率链表移除
RemoveFromFrequencyList(nodeIndex, oldFreq);
// 检查是否需要更新最小频率
if (oldFreq == minFrequency && GetFrequencyListHead(oldFreq) == -1)
{
minFrequency = newFreq;
}
// 更新节点频率
node.frequency = newFreq;
nodes[nodeIndex] = node;
// 添加到新频率链表
AddToFrequencyList(nodeIndex, newFreq);
}
///
/// 从频率链表中移除节点
///
private void RemoveFromFrequencyList(int nodeIndex, int frequency)
{
if (!freqToList.TryGetValue(frequency, out var list))
return;
Node node = nodes[nodeIndex];
// 如果是头节点
if (node.prevIndex == -1)
{
list.headIndex = node.nextIndex;
}
else
{
// 更新前一个节点的next指针
Node prevNode = nodes[node.prevIndex];
prevNode.nextIndex = node.nextIndex;
nodes[node.prevIndex] = prevNode;
}
// 如果是尾节点
if (node.nextIndex == -1)
{
list.tailIndex = node.prevIndex;
}
else
{
// 更新后一个节点的prev指针
Node nextNode = nodes[node.nextIndex];
nextNode.prevIndex = node.prevIndex;
nodes[node.nextIndex] = nextNode;
}
// 如果链表变空,移除该频率
if (list.headIndex == -1)
{
freqToList.Remove(frequency);
}
else
{
freqToList[frequency] = list;
}
}
///
/// 将节点添加到频率链表尾部
///
private void AddToFrequencyList(int nodeIndex, int frequency)
{
if (!freqToList.TryGetValue(frequency, out var list))
{
// 创建新的频率链表
list = new FrequencyList { headIndex = nodeIndex, tailIndex = nodeIndex };
freqToList.Add(frequency, list);
// 设置节点指针
Node node = nodes[nodeIndex];
node.prevIndex = -1;
node.nextIndex = -1;
nodes[nodeIndex] = node;
}
else
{
// 添加到链表尾部
int oldTail = list.tailIndex;
// 更新原尾节点
Node oldTailNode = nodes[oldTail];
oldTailNode.nextIndex = nodeIndex;
nodes[oldTail] = oldTailNode;
// 设置新节点
Node newNode = nodes[nodeIndex];
newNode.prevIndex = oldTail;
newNode.nextIndex = -1;
nodes[nodeIndex] = newNode;
// 更新链表尾
list.tailIndex = nodeIndex;
freqToList[frequency] = list;
}
}
///
/// 获取频率链表的头节点
///
private int GetFrequencyListHead(int frequency)
{
if (freqToList.TryGetValue(frequency, out var list))
{
return list.headIndex;
}
return -1;
}
///
/// 淘汰最小频率的节点(淘汰该频率链表的头节点)
///
private void EvictMinFrequencyNode()
{
// 找到有节点的最小频率
while (minFrequency <= capacity && GetFrequencyListHead(minFrequency) == -1)
{
minFrequency++;
}
if (minFrequency > capacity) return;
int headIndex = GetFrequencyListHead(minFrequency);
if (headIndex == -1) return;
RemoveNode(headIndex);
}
///
/// 移除完整节点(从所有数据结构中删除)
///
private void RemoveNode(int nodeIndex)
{
Node node = nodes[nodeIndex];
// 从频率链表移除
RemoveFromFrequencyList(nodeIndex, node.frequency);
// 从主HashMap移除
keyToNodeIndex.Remove(node.key);
// 回收节点
FreeNode(nodeIndex);
count--;
}
#endregion
// 属性访问器
public readonly int Count => count;
public readonly int Capacity => capacity;
public readonly bool IsCreated => keyToNodeIndex.IsCreated;
}
public struct NativeARCCache : IDisposable
where TKey : unmanaged, IEquatable
where TValue : unmanaged
{
private const int LIST_T1 = 0, LIST_T2 = 1, LIST_B1 = 2, LIST_B2 = 3;
private struct Node
{
public TKey key;
public TValue value;
public byte listType;
public int prevIndex;
public int nextIndex;
}
private NativeHashMap keyToNode;
private NativeList nodes;
private NativeList freeList;
// 四个链表头尾指针
private int t1Head, t1Tail, t2Head, t2Tail, b1Head, b1Tail, b2Head, b2Tail;
private int capacity, t1Count, t2Count, b1Count, b2Count, p;
public NativeARCCache(int capacity, Allocator allocator)
{
this.capacity = capacity;
this.t1Count = this.t2Count = this.b1Count = this.b2Count = 0;
this.p = 0;
t1Head = t1Tail = t2Head = t2Tail = -1;
b1Head = b1Tail = b2Head = b2Tail = -1;
int totalNodes = capacity * 2;
keyToNode = new NativeHashMap(totalNodes, allocator);
nodes = new NativeList(totalNodes, allocator);
freeList = new NativeList(totalNodes, allocator);
nodes.Length = totalNodes;
for (int i = totalNodes - 1; i >= 0; i--)
{
freeList.Add(i);
}
}
public bool TryGetValue(TKey key, out TValue value)
{
if (keyToNode.TryGetValue(key, out int nodeIndex))
{
Node node = nodes[nodeIndex]; // 先读取
if (node.listType == LIST_T1 || node.listType == LIST_T2)
{
MoveToMRU(nodeIndex, LIST_T2);
value = node.value;
return true;
}
if (node.listType == LIST_B1)
{
node = ComputeNewPAndReplace(node, b2Count, b1Count, true);
b1Count--; t2Count++;
value = node.value;
return true;
}
if (node.listType == LIST_B2)
{
node = ComputeNewPAndReplace(node, b1Count, b2Count, false);
b2Count--; t2Count++;
value = node.value;
return true;
}
}
value = default;
return false;
}
public void Put(TKey key, TValue value)
{
if (keyToNode.TryGetValue(key, out int nodeIndex))
{
Node node = nodes[nodeIndex];
node.value = value;
if (node.listType == LIST_T1 || node.listType == LIST_T2)
{
MoveToMRU(nodeIndex, LIST_T2);
}
else if (node.listType == LIST_B1)
{
node = ComputeNewPAndReplace(node, b2Count, b1Count, true);
b1Count--; t2Count++;
}
else if (node.listType == LIST_B2)
{
node = ComputeNewPAndReplace(node, b1Count, b2Count, false);
b2Count--; t2Count++;
}
nodes[nodeIndex] = node; // 写回
return;
}
// 容量满,执行Replace
int totalSize = t1Count + t2Count;
if (totalSize >= capacity)
{
Replace();
}
// 创建新节点到T1
nodeIndex = AllocateNode();
nodes[nodeIndex] = new Node
{
key = key,
value = value,
listType = LIST_T1,
prevIndex = -1,
nextIndex = -1
};
keyToNode.Add(key, nodeIndex);
AddToHead(nodeIndex, LIST_T1);
t1Count++;
}
private Node ComputeNewPAndReplace(Node node, int oppositeCount, int sameCount, bool isB1)
{
int delta = (oppositeCount >= sameCount) ? 1 : oppositeCount / sameCount + 1;
// 先修改p值
if (isB1) p = Math.Min(p + delta, capacity);
else p = Math.Max(p - delta, 0);
// 执行替换
Replace();
// 移动节点
MoveBetweenLists(node.prevIndex, node.listType, LIST_T2);
node.listType = LIST_T2;
return node;
}
private void Replace()
{
if (t1Count > 0 && (t1Count > p || (b2Count > 0 && t1Count == p)))
{
MoveBetweenLists(t1Head, LIST_T1, LIST_B1);
t1Count--; b1Count++;
if (b1Count > capacity)
{
int old = b1Head; Node n = nodes[old];
RemoveFromList(old);
keyToNode.Remove(n.key);
FreeNode(old);
b1Count--;
}
}
else
{
MoveBetweenLists(t2Head, LIST_T2, LIST_B2);
t2Count--; b2Count++;
if (b2Count > capacity)
{
int old = b2Head; Node n = nodes[old];
RemoveFromList(old);
keyToNode.Remove(n.key);
FreeNode(old);
b2Count--;
}
}
}
#region 链表操作
private void MoveToMRU(int nodeIndex, byte targetList)
{
RemoveFromList(nodeIndex);
AddToHead(nodeIndex, targetList);
}
private void MoveBetweenLists(int nodeIndex, byte fromList, byte toList)
{
RemoveFromList(nodeIndex);
AddToHead(nodeIndex, toList);
}
private void AddToHead(int nodeIndex, byte listType)
{
Node node = nodes[nodeIndex]; // 读取
node.listType = listType;
node.prevIndex = -1;
switch (listType)
{
case LIST_T1:
node.nextIndex = t1Head;
nodes[nodeIndex] = node; // 写回
if (t1Head != -1)
{
Node headNode = nodes[t1Head];
headNode.prevIndex = nodeIndex;
nodes[t1Head] = headNode; // 写回
}
t1Head = nodeIndex;
if (t1Tail == -1) t1Tail = nodeIndex;
break;
case LIST_T2:
node.nextIndex = t2Head;
nodes[nodeIndex] = node; // 写回
if (t2Head != -1)
{
Node headNode = nodes[t2Head];
headNode.prevIndex = nodeIndex;
nodes[t2Head] = headNode; // 写回
}
t2Head = nodeIndex;
if (t2Tail == -1) t2Tail = nodeIndex;
break;
case LIST_B1:
node.nextIndex = b1Head;
nodes[nodeIndex] = node; // 写回
if (b1Head != -1)
{
Node headNode = nodes[b1Head];
headNode.prevIndex = nodeIndex;
nodes[b1Head] = headNode; // 写回
}
b1Head = nodeIndex;
if (b1Tail == -1) b1Tail = nodeIndex;
break;
case LIST_B2:
node.nextIndex = b2Head;
nodes[nodeIndex] = node; // 写回
if (b2Head != -1)
{
Node headNode = nodes[b2Head];
headNode.prevIndex = nodeIndex;
nodes[b2Head] = headNode; // 写回
}
b2Head = nodeIndex;
if (b2Tail == -1) b2Tail = nodeIndex;
break;
}
}
private void RemoveFromList(int nodeIndex)
{
Node node = nodes[nodeIndex]; // 读取
int prev = node.prevIndex;
int next = node.nextIndex;
// 根据类型更新头尾指针
switch (node.listType)
{
case LIST_T1:
if (nodeIndex == t1Head) t1Head = next;
if (nodeIndex == t1Tail) t1Tail = prev;
break;
case LIST_T2:
if (nodeIndex == t2Head) t2Head = next;
if (nodeIndex == t2Tail) t2Tail = prev;
break;
case LIST_B1:
if (nodeIndex == b1Head) b1Head = next;
if (nodeIndex == b1Tail) b1Tail = prev;
break;
case LIST_B2:
if (nodeIndex == b2Head) b2Head = next;
if (nodeIndex == b2Tail) b2Tail = prev;
break;
}
// 更新邻居
if (prev != -1)
{
Node prevNode = nodes[prev];
prevNode.nextIndex = next;
nodes[prev] = prevNode; // 写回
}
if (next != -1)
{
Node nextNode = nodes[next];
nextNode.prevIndex = prev;
nodes[next] = nextNode; // 写回
}
node.prevIndex = node.nextIndex = -1;
nodes[nodeIndex] = node; // 写回
}
#endregion
private int AllocateNode()
{
int index = freeList[^1];
freeList.RemoveAtSwapBack(freeList.Length - 1);
return index;
}
private void FreeNode(int index)
{
freeList.Add(index);
}
public bool Remove(TKey key)
{
if (!keyToNode.TryGetValue(key, out int nodeIndex))
return false;
Node node = nodes[nodeIndex]; // 读取
// 更新计数
if (node.listType == LIST_T1) t1Count--;
else if (node.listType == LIST_T2) t2Count--;
else if (node.listType == LIST_B1) b1Count--;
else if (node.listType == LIST_B2) b2Count--;
RemoveFromList(nodeIndex);
keyToNode.Remove(key);
FreeNode(nodeIndex);
return true;
}
public void Clear()
{
keyToNode.Clear();
freeList.Clear();
for (int i = 0; i < nodes.Length; i++)
{
freeList.Add(i);
}
t1Head = t1Tail = t2Head = t2Tail = -1;
b1Head = b1Tail = b2Head = b2Tail = -1;
t1Count = t2Count = b1Count = b2Count = 0;
p = 0;
}
public void Dispose()
{
if (keyToNode.IsCreated) keyToNode.Dispose();
if (nodes.IsCreated) nodes.Dispose();
if (freeList.IsCreated) freeList.Dispose();
t1Head = t1Tail = t2Head = t2Tail = -1;
b1Head = b1Tail = b2Head = b2Tail = -1;
t1Count = t2Count = b1Count = b2Count = 0;
p = 0;
}
public int Count => t1Count + t2Count;
public int Capacity => capacity;
public bool IsCreated => keyToNode.IsCreated;
public int T1Count => t1Count;
public int T2Count => t2Count;
public int PValue => p;
}
}
}