Kselax.ru

Hacker Kselax — the best hacker in the world

Menu
  • Блог
  • Контакты
  • wp plugin генератор
  • Русский
    • Русский
    • English
Menu

Реализация Pool_alloc.

Posted on 21 июля, 201329 июля, 2013 by admin

Завершите или реализуйте с самого начала Pool_alloc (параграф 19.4.2) так, чтобы обеспечивались все возможности стандартного аллокатора allocator (параграф 19.4.1) из стандартной библиотеки. Сравните производительности Pool_alloc и allocator, чтобы решить, стоит ли использовать Pool_alloc в вашей системе.

Пытался я разобраться в том коде что в книге, но так не сильно разобрался, как то не охота вникать, код как оказалось не такой и простой, что то там выделяется хз что. В общем закомментировал я его, он не заработал, вылазят ошибки, когда компилирую для vector или map, поэтому просто щас его скину, что бы не парится, не правильный он какой то, пока что отложу, возможно потом когда понадобится вернусь к нему.

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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//Pool_alloc
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <map>
using std::map;
#include <string>
using std::string;
#include <utility>
using std::pair;
#include <functional>
using std::less;
 
class Pool//переводится как басейн
{
struct Link{Link* next;};
 
struct Chunk//переводится как кусок
{
enum{size=8*1024-16};//слегка менше 8К, чтобы кусок памяти умещался в 8К
char mem[size];//для достижения точного выравнивания
Chunk* next;//указатель на следующий кусок
};
 
Chunk* chunks;//указатель на куски
const unsigned int esize;//размер элемента видимо в байтах, а мб хз.
Link* head; //ссылка на голову
//конструктор копирования
Pool (Pool&); //защита от копирования
//оператор присваивания
void operator=(Pool&);//защита от копирования
//увеличить басейн
void grow();//увеличить пул
 
public:
//конструктор преобразования
Pool(unsigned int n);//n это размер элементов
~Pool();//деструктор
//выделяет память
void* alloc();//выделить память под один элемент
//освобождение памяти
void free(void* b);//возвращение элемента в пул
};
 
//функция выделения памяти
//inline функция явно прописывается в коде без вызова
//void* возвращает любой тип
inline void* Pool::alloc()
{
//ессли начало рано ноль, то увеличить басейн
if(head==0)grow();
Link* p=head;//вернуть первый элемент
head=p->next;
return p;
}
 
//освобождение памяти принимает любой указатель
//похоже освобождение без уничтожения объекта
inline void Pool::free(void* b)
{
//преобразование указателя в link
Link* p=static_cast<Link*>(b);//грубое преобразование типа void* в тип Link*
p->next=head;//член next = голова
head=p;//голова равняется p указатель на Link*
}
 
//конструктор преобразования
//sz-размер элемента
Pool::Pool(unsigned int sz)
:esize(sz<sizeof(Link)?sizeof(Link):sz)//если меньше то sizeof(Link), если больше то sz
{
head=0;//голова 0
chunks=0;//кусок 0
}
 
Pool::~Pool()//освободить все куски (chunks)
{
Chunk* n=chunks;
while(n)//пока n не 0
{
Chunk* p=n;
n=n->next;//сделанно в виде списка
delete p;//освободить память
}
}
 
void Pool::grow()//выделяет новый 'chunk', организуя его в виде связанного
//списка элементов размером 'esize'
{
Chunk* n=new Chunk;//выделение нового куска
n->next=chunks;//сначала равно 0, а затем уже видимо на следующий кусок ссылка
chunks=n;//указатель присваивается на новый выделенный кусок
 
//nelem=size из Chunk разделить на размер элемента
//size=8*1024-16 8 килобайт вроде как чуть меньше
//nelem это количество элементов которое видимо выделено может быть.
const int nelem=Chunk::size/esize;
//указатель на char* start (n->mem где mem это массив mem[size] иил mem[8*1024-16], примерно 8К)
char* start=n->mem;
//конец равен количеству элементов минус 1 и умноженое на размер элемента, это просто указатель на последний элемент
char* last=&start[(nelem-1)*esize];//указывает похоже на элемент за последним
 
//цикл от начала и до конца
//памяти похоже сразу выделено 8К мы просто проходим по этой памяти
//и делим, токо я не пойму как мы ее делим, p на начало указывает, p->next=p+esize, то есть указатель
//плюс размер элемента, получается как то мы еще и по элементу пробигамем после того как мы к
//p прибавили esize мы как бы переместили указатель и теперь он стал чуть дальше на esize
//в общем мы просто тут похоже как бы формируем связаный список из кусков памяти размером esize.
for(char*p=start;p<last;p+=esize)
reinterpret_cast<Link*>(p)->next=reinterpret_cast<Link*>(p+esize);
 
reinterpret_cast<Link*>(last)->next=0;//последний элемент списка равен 0
head=reinterpret_cast<Link*>(start);//первый элемент списка указывает на начало как бы связи
//какой то этот код в понимании ни такой простой как кажется, даже после моей расписки что куда идет не сильно понятно
}
 
template<class T> class Pool_alloc
{
private:
//статический член
static Pool mem;//пул элементов размером sizeof(T)
 
public:
//аналогично стандартному аллокатору(19.4.1)
typedef unsigned int size_type;
typedef T* pointer;
typedef unsigned int difference_type;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
 
Pool_alloc();
//конструктор копирования
Pool_alloc(const Pool_alloc<T>& a):mem(a.mem){}
T* allocate(size_type,void*);
void deallocate(pointer p,size_type n);
template<class Other>
   struct rebind{
      typedef Pool_alloc<Other> other;
};
};
 
//инициализация статического члена
template<class T> Pool Pool_alloc<T>::mem(sizeof(T));
 
template<class T> Pool_alloc<T>::Pool_alloc(){}
 
template<class T>
T* Pool_alloc<T>::allocate(size_type n,void* k)
{
//если n==1, то мы вызываем mem.alloc
if(n==1)return static_cast<T*>(mem.alloc());
//...
}
 
template<class T>
void Pool_alloc<T>::deallocate(pointer p,size_type n)
{
if(n==1)
{
mem.free(p);
return;
}
//...
}
 
int main()
{
cout <<"Pool alloc"<<endl;
vector<int,Pool_alloc<int> >v;
v.push_back(1);
cout <<v[0]<<endl;
map<string,int,less<int>/*,Pool_alloc<pair<const string,int> >*/ >m;
//m["hellow"]=33;
//m["world"]=40;
//cout <<m["hellow"]<<m["world"]<<endl;
 
return 0;
}

Я вообще надеюсь что не понадобится, щас попробуем просто свой аллокатор создать без всяких там Pool

Неохота мне голову морочит вот свой собственный аллокатор, подсмотрел реализацию на форуме.

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
#include <iostream>
using std::cout;
using std::endl;
#include <allocators>
 
template<class T>
class allocator : public std::allocator<T>
{
public:
typedef allocator<T> base;
void* allocate(typename base::size_type n, void* =0)
{
return malloc(n*sizeof(T));
}
void deallocate(void* p)
{
free(p);
}
void construct(void* p, const T& value)
{
new (p) T(value);
}
void destuct(T* p)
{
p->~T();
}
};
 
int main()
{
allocator<int> a;
int* p;
p=static_cast<int*>(malloc(7*sizeof(int)));
int* p1=p;
for(int i=0;i<7;i++)
{
a.construct(p,4);
p++;
}
p=p1;
for(int i=0;i<7;i++)
{
cout <<*p<<endl;
p++;
}
 
a.deallocate(p1);
 
return 0;
}

Щас еще подсмотрю реализацию, чтобы можно было использовать в стандартных контейнерах, там есть. От все таки получилось и для вектора создать аллокатор, опять же без посторонней помощи не обошлось, жаль конечно.

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
#include <iostream>
using std::cout;
using std::endl;
#include <allocators>
#include <vector>
using std::vector;
 
template<class T>
class allocator : public std::allocator<T>
{
public:
typedef allocator<T> base;
typename base::pointer allocate(typename base::size_type n, void* =0)
{
return static_cast<typename base::pointer>(malloc(n*sizeof(T)));
}
void deallocate(void* p)
{
free(p);
}
void construct(void* p, const T& value)
{
new (p) T(value);
}
void destuct(T* p)
{
p->~T();
}
};
 
int main()
{
allocator<int> a;
int* p;
p=static_cast<int*>(malloc(7*sizeof(int)));
int* p1=p;
for(int i=0;i<7;i++)
{
a.construct(p,4);
p++;
}
p=p1;
for(int i=0;i<7;i++)
{
cout <<*p<<endl;
p++;
}
 
a.deallocate(p1);
 
vector<int,allocator<int> > v;
v.push_back(5);
cout <<v[0]<<endl;
 
return 0;
}

[youtube]http://www.youtube.com/watch?v=_rsnNWAZde0[/youtube]

Добавить комментарий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Рубрики

  • C++ (293)
  • JavaScript (1)
  • linux (1)
  • MFC (39)
  • node.js (2)
  • React (3)
  • vBulletin (5)
  • Visual Studio (9)
  • wordpress (18)
  • Разное (29)

Метки

Ajax bootstrap CentOS CLI expressjs FormData GDlib google Invisible reCAPTCHA JWT media MFC php react-router-dom redux repository wordpress RTTI STL vBulletin vector Visual Studio WINAPI wordpress wp-plugins XMLHttpRequest Двоичное дерево Задачи С++ Игры С++ Исключения С++ О-большое Операторы_С++ Перегрузка операторов С++ Поиск С++ Потоки Проектирование_С++ С++ Типы_С++ Типы С++ Шаблоны С++ библиотеки локализация макросы С++ сортировка С++

Свежие комментарии

  • RA3PKJ к записи visual C++, создание диалоговых окон.
  • JasonReant к записи Создание и использование статических библиотек .lib в visual studio.
  • MyWin2020 к записи Программка для заполнения форума на vBulletin 3.8.7
  • ScottJip к записи Создание и использование статических библиотек .lib в visual studio.
  • ArnoldKig к записи Создание и использование статических библиотек .lib в visual studio.
©2021 Kselax.ru Theme by ThemeGiant