/// <summary> /// Disposes and releases all allocations back to the system. /// Will print diagnostics about potential memory leaks. /// </summary> public void Dispose() { if (!IsCreated) { throw new ObjectDisposedException("Managed memory allocator disposed"); } int memoryLeaks = 0; PageNode *head = GetHeadPage(); PageNode *current = head; while (current != null) { memoryLeaks += current->MemoryPage.ObjectsInUse(); var old = current; current = current->Next; // The head page node is allocated in-place in the Impl, so it shouldn't be free'd here. // Small memory locality optimization for few instances of many types. if (old != head) { FreeNode(old); } } if (memoryLeaks > 0) { Debug.LogWarning($"{memoryLeaks} memory leak(s) found while disposing ManagedMemoryAllocator"); } UnsafeUtility.Free(m_Impl, Allocator.Persistent); this = new ManagedMemoryAllocator(); }
/// <summary> /// Allocates an object with the properties given in the constructor. /// Contents guaranteed to be zero-initialized. /// Throws exception if out of memory, otherwise won't fail. /// </summary> /// <remarks> /// Must be free'd through ManagedMemoryAllocator.Free(). /// </remarks> public void *Alloc() { if (!IsCreated) { throw new ObjectDisposedException("Managed memory allocator disposed"); } PageNode *current = null; void * memory = null; // see if we have a page in the list with a free object for (current = GetHeadPage(); ; current = current->Next) { memory = current->MemoryPage.Alloc(); if (memory != null) { return(memory); } // reached end of list, have to create a new if (current->Next == null) { current->Next = CreateNode(); memory = current->Next->MemoryPage.Alloc(); if (memory != null) { return(memory); } throw new OutOfMemoryException(); } } }
void FreeNode(PageNode *node) { Page.DestroyPage(&node->MemoryPage); UnsafeUtility.Free(node, Allocator.Persistent); }
void InitializeNode(PageNode *node) { Page.InitializePage(&node->MemoryPage, m_Impl->ObjectSize, m_Impl->ObjectAlign, m_Impl->PoolSize); node->Next = null; }