File: Allocator.h

package info (click to toggle)
ergo 3.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 17,396 kB
  • sloc: cpp: 94,740; ansic: 17,015; sh: 7,559; makefile: 1,402; yacc: 127; lex: 110; awk: 23
file content (125 lines) | stat: -rw-r--r-- 4,021 bytes parent folder | download
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