1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
/* Ergo, version 3.8, a program for linear scaling electronic structure
* calculations.
* Copyright (C) 2019 Elias Rudberg, Emanuel H. Rubensson, Pawel Salek,
* and Anastasia Kruchinina.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Primary academic reference:
* Ergo: An open-source program for linear-scaling electronic structure
* calculations,
* Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, and Anastasia
* Kruchinina,
* SoftwareX 7, 107 (2018),
* <http://dx.doi.org/10.1016/j.softx.2018.03.005>
*
* For further information about Ergo, see <http://www.ergoscf.org>.
*/
/** @file Allocator.h
\brief Code for Allocator class used for memory
allocation/deallocation in matrix library. The idea of the
Allocator class is that it manages a list of buffers of identical
size, keeping track of where the next available free buffer
is. This functionality can be used for allocating submatrices in
the matrix library, since almost all submatrices have identical
size.
@author Elias Rudberg
*/
#ifndef MAT_ALLOCATOR_HEADER
#define MAT_ALLOCATOR_HEADER
#include <stdexcept>
namespace mat {
template<class Treal>
class Allocator
{
public:
Allocator(int noOfRealsPerBuffer_,
int noOfBuffers_) :
noOfRealsPerBuffer(noOfRealsPerBuffer_),
noOfBuffers(noOfBuffers_)
{
buffer = new Treal[noOfBuffers * noOfRealsPerBuffer];
nextFreeIndexList = new int[noOfBuffers];
// Initialize nextFreeIndexList to indicate that all slots are free.
for(int i = 0; i < noOfBuffers-1; i++)
nextFreeIndexList[i] = i + 1;
nextFreeIndexList[noOfBuffers-1] = -1; // last one points to -1
firstFreeIndex = 0;
noOfOccupiedSlots = 0;
}
~Allocator()
{
delete [] buffer;
delete [] nextFreeIndexList;
}
Treal* alloc() {
if(firstFreeIndex < 0)
throw std::runtime_error("Error in Allocator::alloc(): no free slots.");
Treal* ptrToReturn = &buffer[firstFreeIndex*noOfRealsPerBuffer];
int firstFreeIndex_new = nextFreeIndexList[firstFreeIndex];
nextFreeIndexList[firstFreeIndex] = -1;
firstFreeIndex = firstFreeIndex_new;
noOfOccupiedSlots++;
return ptrToReturn;
}
void free(Treal* ptr) {
if(ptr < buffer || ptr >= &buffer[noOfBuffers * noOfRealsPerBuffer])
throw std::runtime_error("Error in Allocator::free(): unknown ptr.");
int count = ptr - buffer;
if((count % noOfRealsPerBuffer) != 0)
throw std::runtime_error("Error in Allocator::free(): bad ptr.");
int bufferIdx = count / noOfRealsPerBuffer;
if(nextFreeIndexList[bufferIdx] != -1)
throw std::runtime_error("Error in Allocator::free(): -1 not found.");
nextFreeIndexList[bufferIdx] = firstFreeIndex;
firstFreeIndex = bufferIdx;
noOfOccupiedSlots--;
}
bool isFull() {
if(noOfOccupiedSlots == noOfBuffers)
return true;
return false;
}
bool isEmpty() {
if(noOfOccupiedSlots == 0)
return true;
return false;
}
bool ownsPtr(Treal* ptr) {
if(ptr < buffer || ptr >= &buffer[noOfBuffers * noOfRealsPerBuffer])
return false;
return true;
}
int getNoOfOccupiedSlots() {
return noOfOccupiedSlots;
}
private:
int noOfRealsPerBuffer;
int noOfBuffers;
Treal* buffer;
int* nextFreeIndexList;
int firstFreeIndex;
int noOfOccupiedSlots;
}; // end class Allocator
} /* end namespace mat */
#endif
|