From 223df3fb9168796af50eadf9c1ed87cc1c9ec5e8 Mon Sep 17 00:00:00 2001
From: ninemine <1371605831@qq.com>
Date: Fri, 5 Dec 2025 16:25:40 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=80=A7=E8=83=BD=E5=AE=B9?=
=?UTF-8?q?=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Modules/ObjectPoolManager.cs | 1 +
.../[Runtime]/Convention.Collections.cs | 982 ++++++++++++++++++
2 files changed, 983 insertions(+)
diff --git a/Convention/[Architecture]/Modules/ObjectPoolManager.cs b/Convention/[Architecture]/Modules/ObjectPoolManager.cs
index 06916fb..8576ed0 100644
--- a/Convention/[Architecture]/Modules/ObjectPoolManager.cs
+++ b/Convention/[Architecture]/Modules/ObjectPoolManager.cs
@@ -109,6 +109,7 @@ namespace Convention.Experimental.Modules
}
else
{
+ Debug.LogError("This object does not belong to any pool.", instance);
throw new PublicType.GameException("This object does not belong to any pool.");
}
}
diff --git a/Convention/[Runtime]/Convention.Collections.cs b/Convention/[Runtime]/Convention.Collections.cs
index ec79408..cf7838f 100644
--- a/Convention/[Runtime]/Convention.Collections.cs
+++ b/Convention/[Runtime]/Convention.Collections.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using Unity.Collections;
namespace Convention.Collections
{
@@ -453,4 +454,985 @@ namespace Convention.Collections
}
}
}
+
+ 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;
+ }
+ }
}
\ No newline at end of file