// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #ifndef MFEM_MEM_ALLOC #define MFEM_MEM_ALLOC #include "../config/config.hpp" #include "array.hpp" // mfem::Swap namespace mfem { template class StackPart { public: StackPart *Prev; Elem Elements[Num]; }; template class Stack { private: StackPart *TopPart, *TopFreePart; int UsedInTop, SSize; public: /// Construct an empty stack. Stack() { TopPart = TopFreePart = NULL; UsedInTop = Num; SSize = 0; } /// Return the number of elements on the stack. int Size() const { return SSize; } /// Push element 'E' on the stack. void Push (Elem E); /// Pop an element off the stack and return it. Elem Pop(); /// Clear the elements off the stack. void Clear(); /// Swap the data in this stack with the data in @a other. void Swap(Stack &other); /// Return the number of bytes used by the stack. size_t MemoryUsage() const; ~Stack() { Clear(); } }; template void Stack ::Push (Elem E) { StackPart *aux; if (UsedInTop == Num) { if (TopFreePart == NULL) { aux = new StackPart ; } else { TopFreePart = (aux = TopFreePart)->Prev; } aux->Prev = TopPart; TopPart = aux; UsedInTop = 0; } TopPart->Elements[UsedInTop++] = E; SSize++; } template Elem Stack ::Pop() { StackPart *aux; if (UsedInTop == 0) { TopPart = (aux = TopPart)->Prev; aux->Prev = TopFreePart; TopFreePart = aux; UsedInTop = Num; } SSize--; return TopPart->Elements[--UsedInTop]; } template void Stack ::Clear() { StackPart *aux; while (TopPart != NULL) { TopPart = (aux = TopPart)->Prev; delete aux; } while (TopFreePart != NULL) { TopFreePart = (aux = TopFreePart)->Prev; delete aux; } UsedInTop = Num; SSize = 0; } template void Stack::Swap(Stack &other) { mfem::Swap(TopPart, other.TopPart); mfem::Swap(TopFreePart, other.TopFreePart); mfem::Swap(UsedInTop, other.UsedInTop); mfem::Swap(SSize, other.SSize); } template size_t Stack ::MemoryUsage() const { size_t used_mem = 0; StackPart *aux = TopPart; while (aux != NULL) { used_mem += sizeof(StackPart ); aux = aux->Prev; } aux = TopFreePart; while (aux != NULL) { used_mem += sizeof(StackPart ); aux = aux->Prev; } // Not counting sizeof(Stack ) return used_mem; } template class MemAllocNode { public: MemAllocNode *Prev; Elem Elements[Num]; }; template class MemAlloc { private: MemAllocNode *Last; int AllocatedInLast; Stack UsedMem; public: MemAlloc() { Last = NULL; AllocatedInLast = Num; } Elem *Alloc(); void Free (Elem *); void Clear(); void Swap(MemAlloc &other); size_t MemoryUsage() const; ~MemAlloc() { Clear(); } }; template Elem *MemAlloc ::Alloc() { MemAllocNode *aux; if (UsedMem.Size() > 0) { return UsedMem.Pop(); } if (AllocatedInLast == Num) { aux = Last; Last = new MemAllocNode ; Last->Prev = aux; AllocatedInLast = 0; } return &(Last->Elements[AllocatedInLast++]); } template void MemAlloc ::Free (Elem *E) { UsedMem.Push (E); } template void MemAlloc ::Clear() { MemAllocNode *aux; while (Last != NULL) { aux = Last->Prev; delete Last; Last = aux; } AllocatedInLast = Num; UsedMem.Clear(); } template void MemAlloc::Swap(MemAlloc &other) { mfem::Swap(Last, other.Last); mfem::Swap(AllocatedInLast, other.AllocatedInLast); UsedMem.Swap(other.UsedMem); } template size_t MemAlloc ::MemoryUsage() const { size_t used_mem = UsedMem.MemoryUsage(); MemAllocNode *aux = Last; while (aux != NULL) { used_mem += sizeof(MemAllocNode ); aux = aux->Prev; } // Not counting sizeof(MemAlloc ) return used_mem; } } #endif