228 lines
4.9 KiB
C++
228 lines
4.9 KiB
C++
// Copyright (c) 2010-2020, 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 Elem, int Num>
|
|
class StackPart
|
|
{
|
|
public:
|
|
StackPart<Elem, Num> *Prev;
|
|
Elem Elements[Num];
|
|
};
|
|
|
|
template <class Elem, int Num>
|
|
class Stack
|
|
{
|
|
private:
|
|
StackPart <Elem, Num> *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<Elem, Num> &other);
|
|
|
|
/// Return the number of bytes used by the stack.
|
|
size_t MemoryUsage() const;
|
|
~Stack() { Clear(); }
|
|
};
|
|
|
|
template <class Elem, int Num>
|
|
void Stack <Elem, Num>::Push (Elem E)
|
|
{
|
|
StackPart <Elem, Num> *aux;
|
|
if (UsedInTop == Num)
|
|
{
|
|
if (TopFreePart == NULL)
|
|
{
|
|
aux = new StackPart <Elem, Num>;
|
|
}
|
|
else
|
|
{
|
|
TopFreePart = (aux = TopFreePart)->Prev;
|
|
}
|
|
aux->Prev = TopPart;
|
|
TopPart = aux;
|
|
UsedInTop = 0;
|
|
}
|
|
TopPart->Elements[UsedInTop++] = E;
|
|
SSize++;
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
Elem Stack <Elem, Num>::Pop()
|
|
{
|
|
StackPart <Elem, Num> *aux;
|
|
if (UsedInTop == 0)
|
|
{
|
|
TopPart = (aux = TopPart)->Prev;
|
|
aux->Prev = TopFreePart;
|
|
TopFreePart = aux;
|
|
UsedInTop = Num;
|
|
}
|
|
SSize--;
|
|
return TopPart->Elements[--UsedInTop];
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
void Stack <Elem, Num>::Clear()
|
|
{
|
|
StackPart <Elem, Num> *aux;
|
|
while (TopPart != NULL)
|
|
{
|
|
TopPart = (aux = TopPart)->Prev;
|
|
delete aux;
|
|
}
|
|
while (TopFreePart != NULL)
|
|
{
|
|
TopFreePart = (aux = TopFreePart)->Prev;
|
|
delete aux;
|
|
}
|
|
UsedInTop = Num;
|
|
SSize = 0;
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
void Stack<Elem, Num>::Swap(Stack<Elem, Num> &other)
|
|
{
|
|
mfem::Swap(TopPart, other.TopPart);
|
|
mfem::Swap(TopFreePart, other.TopFreePart);
|
|
mfem::Swap(UsedInTop, other.UsedInTop);
|
|
mfem::Swap(SSize, other.SSize);
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
size_t Stack <Elem, Num>::MemoryUsage() const
|
|
{
|
|
size_t used_mem = 0;
|
|
StackPart <Elem, Num> *aux = TopPart;
|
|
while (aux != NULL)
|
|
{
|
|
used_mem += sizeof(StackPart <Elem, Num>);
|
|
aux = aux->Prev;
|
|
}
|
|
aux = TopFreePart;
|
|
while (aux != NULL)
|
|
{
|
|
used_mem += sizeof(StackPart <Elem, Num>);
|
|
aux = aux->Prev;
|
|
}
|
|
// Not counting sizeof(Stack <Elem, Num>)
|
|
return used_mem;
|
|
}
|
|
|
|
|
|
template <class Elem, int Num>
|
|
class MemAllocNode
|
|
{
|
|
public:
|
|
MemAllocNode <Elem, Num> *Prev;
|
|
Elem Elements[Num];
|
|
};
|
|
|
|
template <class Elem, int Num>
|
|
class MemAlloc
|
|
{
|
|
private:
|
|
MemAllocNode <Elem, Num> *Last;
|
|
int AllocatedInLast;
|
|
Stack <Elem *, Num> UsedMem;
|
|
public:
|
|
MemAlloc() { Last = NULL; AllocatedInLast = Num; }
|
|
Elem *Alloc();
|
|
void Free (Elem *);
|
|
void Clear();
|
|
void Swap(MemAlloc<Elem, Num> &other);
|
|
size_t MemoryUsage() const;
|
|
~MemAlloc() { Clear(); }
|
|
};
|
|
|
|
template <class Elem, int Num>
|
|
Elem *MemAlloc <Elem, Num>::Alloc()
|
|
{
|
|
MemAllocNode <Elem, Num> *aux;
|
|
if (UsedMem.Size() > 0)
|
|
{
|
|
return UsedMem.Pop();
|
|
}
|
|
if (AllocatedInLast == Num)
|
|
{
|
|
aux = Last;
|
|
Last = new MemAllocNode <Elem, Num>;
|
|
Last->Prev = aux;
|
|
AllocatedInLast = 0;
|
|
}
|
|
return &(Last->Elements[AllocatedInLast++]);
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
void MemAlloc <Elem, Num>::Free (Elem *E)
|
|
{
|
|
UsedMem.Push (E);
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
void MemAlloc <Elem, Num>::Clear()
|
|
{
|
|
MemAllocNode <Elem, Num> *aux;
|
|
while (Last != NULL)
|
|
{
|
|
aux = Last->Prev;
|
|
delete Last;
|
|
Last = aux;
|
|
}
|
|
AllocatedInLast = Num;
|
|
UsedMem.Clear();
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
void MemAlloc<Elem, Num>::Swap(MemAlloc<Elem, Num> &other)
|
|
{
|
|
mfem::Swap(Last, other.Last);
|
|
mfem::Swap(AllocatedInLast, other.AllocatedInLast);
|
|
UsedMem.Swap(other.UsedMem);
|
|
}
|
|
|
|
template <class Elem, int Num>
|
|
size_t MemAlloc <Elem, Num>::MemoryUsage() const
|
|
{
|
|
size_t used_mem = UsedMem.MemoryUsage();
|
|
MemAllocNode <Elem, Num> *aux = Last;
|
|
while (aux != NULL)
|
|
{
|
|
used_mem += sizeof(MemAllocNode <Elem, Num>);
|
|
aux = aux->Prev;
|
|
}
|
|
// Not counting sizeof(MemAlloc <Elem, Num>)
|
|
return used_mem;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|