using System; using System.Collections.Generic; namespace Sog { //结构对象需要实现这个接口 public interface IStructObject { int GetObjectID(); void SetObjectID(int id); bool IsNull();//空结构,代替空指针,表示无效 } public class StructMemoryCache where ST : struct, IStructObject { //数组 private ST m_empty; private ST[] m_array; private int[] m_indexStat; public Queue m_freeQueue = new Queue(); public StructMemoryCache(long count) { m_empty.SetObjectID(-1); m_array = new ST[count]; m_indexStat = new int[count]; //第一个默认为空,不要动了 ref ST tobject1 = ref m_array[0]; tobject1.SetObjectID(-1); for (int i = 1; i < m_array.Length; i++) { //设置ID ref ST tobject = ref m_array[i]; tobject.SetObjectID(i); //对象id为0的不要了,方便代码处理,0表示无效 m_freeQueue.Enqueue(i); } } public int GetTotalCount() { return m_array.Length; } public int GetFreeCount() { return m_freeQueue.Count; } public int GetUsedCount() { return GetTotalCount() - GetFreeCount(); } public ref ST Malloc() { if (m_freeQueue.Count == 0) { TraceLog.Error("StructMemoryCache.Malloc no free space"); return ref m_empty; } long index = m_freeQueue.Dequeue(); if (m_indexStat[index] == 1) { TraceLog.Error("StructMemoryCache.Malloc index {0} already be used", index); return ref m_empty; } m_indexStat[index] = 1; m_array[index].SetObjectID((int)index); return ref m_array[index]; } // 自己管理index时, 不要调用Free, 也不要和Malloc()混用 // 最好不要自己管理index public ref ST Malloc(long index) { if (m_freeQueue.Count == 0) { TraceLog.Error("StructMemoryCache.Malloc no free space"); return ref m_empty; } if (m_indexStat[index] == 1) { TraceLog.Error("StructMemoryCache.Malloc index {0} already be used", index); return ref m_empty; } m_indexStat[index] = 1; m_array[index].SetObjectID((int)index); return ref m_array[index]; } public void Free(ref ST tobject) { int index = tobject.GetObjectID(); if (m_indexStat[index] == 0) { return; } // objectId也必须清空 m_array[index].SetObjectID(-1); m_indexStat[index] = 0; m_freeQueue.Enqueue(index); } public void Free(long index) { if (m_indexStat[index] == 0) { return; } // objectId也必须清空 m_array[index].SetObjectID(-1); m_indexStat[index] = 0; m_freeQueue.Enqueue(index); } public ref ST GetByIndex(long index) { if (index >= m_indexStat.Length) { TraceLog.Trace("StructMemoryCache.GetByIndex index {0} is too large", index); return ref m_empty; } if (m_indexStat[index] == 0) { //太多日志了 //TraceLog.Error("StructMemoryCache.GetByIndex index {0} is free, invalid", index); return ref m_empty; } return ref m_array[index]; } public int GetUsedPercent() { if (GetTotalCount() > 0) { return Convert.ToInt32(GetUsedCount() * 100.0 / GetTotalCount()); } return 0; } public int GetUsedIndex(int startIdx) { for (int i = startIdx; i < m_indexStat.Length; i++) { if (m_indexStat[i] > 0) { return i; } } return 0; } } }