-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathPushAllocator.hpp
71 lines (64 loc) · 3.02 KB
/
PushAllocator.hpp
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
#ifndef ___INANITY_PUSH_ALLOCATOR_HPP___
#define ___INANITY_PUSH_ALLOCATOR_HPP___
#include "MemoryFile.hpp"
#include <vector>
BEGIN_INANITY
/// Класс расширяющегося аллокатора памяти для объектов.
/** Он может только создавать новые объекты, или уничтожить все,
* когда уничтожается. Объекты, конечно, не могут быть управляемыми,
* так как они не лежат в управляемой куче.
* Класс несколько эффективней вектора, так как не производит перевыделения
* памяти, и копирования объектов на новое место.
* Кроме того, он обладает преимуществом - указатели на выданные объекты остаются
* валидными, пока аллокатор жив.
* Аллокатор эффективно выделяет память, выполняя логарифм выделений,
* и в любой момент не превышая объём необходимой памяти более чем в два раза.
* Объекты должны иметь конструктор по умолчанию. */
template <typename T>
class PushAllocator : public Object
{
private:
/// Файлы, в которых выделена память.
std::vector<ptr<MemoryFile> > files;
/// Общее количество инициализированных объектов.
size_t objectsCount;
/// Размер последнего файла в объектах.
size_t lastFileAllCount;
/// Сколько объектов выделено в последнем файле.
size_t lastFileAllocatedCount;
/// Память последнего файла.
T* lastFileData;
public:
/// Создать аллокатор.
PushAllocator() : objectsCount(0), lastFileAllCount(0), lastFileAllocatedCount(0), lastFileData(0) {}
/// Уничтожить аллокатор вместе со всеми объектами.
~PushAllocator()
{
for(size_t i = 0; i < files.size(); ++i)
{
ptr<MemoryFile> file = files[i];
T* objects = (T*)file->GetData();
size_t fileObjectsCount = file->GetSize() / sizeof(T);
for(size_t j = 0; j < fileObjectsCount && objectsCount > 0; ++j, --objectsCount)
objects[j].~T();
}
}
/// Создать объект.
T* Allocate()
{
// если в последнем файле больше нет места
if(lastFileAllocatedCount >= lastFileAllCount)
{
// создать новый файл
lastFileAllCount = 1 << files.size();
ptr<MemoryFile> newFile = NEW(MemoryFile(lastFileAllCount * sizeof(T)));
files.push_back(newFile);
lastFileAllocatedCount = 0;
lastFileData = (T*)newFile->GetData();
}
// выделить память, и вызвать конструктор
return new (lastFileData + lastFileAllocatedCount++) T();
}
};
END_INANITY
#endif