Требуется опыт Boost Pool. Это полезно в качестве распределителя с предварительным распределением?

Недавно я искал механизм пула / распределения.
Boost Pool, кажется, обеспечивает решение, но есть еще вещи, которые он не смог вывести из документации.

Что нужно выделить

  1. Несколько небольших классов (~ 30 символов)
  2. std :: map (я хочу убедиться, что он не выполняет динамический распределитель сам по себе)
  3. размещение в pugi :: xml
  4. СТД :: строки

Как контролировать адресное пространство для размещения (или просто количество)

Кажется, что object_pool обеспечивает хороший способ для распределения потребностей 1)
Однако он хотел бы установить фиксированный размер для использования распределителем. По умолчанию он захватывает память быть самим собой.
Если возможно, я бы хотел дать ему адресное пространство, в котором он может играть.

char * mem_for_class[1024*1024];
boost::object_pool<my_class,mem_for_class> q;

или же:

const int max_no_objs=1024;
boost::object_pool<my_class,max_no_objs> q;

Хотя UserAllocator доступен в Boost :: Pool; кажется, победить суть. Боюсь, что необходимый контроль сделает его слишком неэффективным … и было бы лучше начать с нуля.

Можно ли установить фиксированную область для pool_allocator?

Вопрос немного похож на первый.
Обеспечивает ли пул наддува любой способ ограничения того, сколько / где выделено памяти при передаче boost :: pool_allocator классу std-type (например, map)

Мой сценарий

Встроенное программирование Linux. Система должна продолжать работать вечно. Поэтому мы не можем рисковать любой сегментацией памяти. В настоящее время я в основном либо статическое распределение (стек), но также несколько необработанных «новых».
Я хотел бы схему распределения, которая гарантирует, что я использую одну и ту же область памяти каждый раз, когда программа зацикливается.
Скорость / пространство важны, но безопасность по-прежнему является главным приоритетом.

Я надеюсь, что StackOverflow — это место, где можно спросить. Я безуспешно пытался связаться с автором Boost :: Pool «Stephen». Я не нашел ни одного форума для Boost.

6

Решение

Вы всегда можете создать распределитель, который работает с STL. Если он работает с STL, он должен работать с boost, так как вы можете передавать boost-распределители в контейнеры STL.

Учитывая вышесказанное, распределитель, который может выделяться по указанному адресу памяти И, имеет указанное вами ограничение размера, можно записать следующим образом:

#include <iostream>
#include <vector>

template<typename T>
class CAllocator
{
private:
std::size_t size;
T* data = nullptr;

public:
typedef T* pointer;
typedef const T* const_pointer;

typedef T& reference;
typedef const T& const_reference;

typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

typedef T value_type;CAllocator() {}
CAllocator(pointer data_ptr, size_type max_size) noexcept : size(max_size), data(data_ptr) {};

template<typename U>
CAllocator(const CAllocator<U>& other) noexcept {};

CAllocator(const CAllocator &other) : size(other.size), data(other.data) {}

template<typename U>
struct rebind {typedef CAllocator<U> other;};

pointer allocate(size_type n, const void* hint = 0) {return &data[0];}
void deallocate(void* ptr, size_type n) {}
size_type max_size() const {return size;}
};

template <typename T, typename U>
inline bool operator == (const CAllocator<T>&, const CAllocator<U>&) {return true;}

template <typename T, typename U>
inline bool operator != (const CAllocator<T>& a, const CAllocator<U>& b) {return !(a == b);}
int main()
{
const int size = 1024 / 4;
int ptr[size];
std::vector<int, CAllocator<int>> vec(CAllocator<int>(&ptr[0], size));

int ptr2[size];
std::vector<int, CAllocator<int>> vec2(CAllocator<int>(&ptr2[0], size));

vec.push_back(10);
vec.push_back(20);
vec2.push_back(30);
vec2.push_back(40);for (std::size_t i = 0; i < vec2.size(); ++i)
{
int* val = &ptr2[i];
std::cout<<*val<<"\n";
}

std::cout<<"\n\n";

vec2 = vec;

for (std::size_t i = 0; i < vec2.size(); ++i)
{
int* val = &ptr2[i];
std::cout<<*val<<"\n";
}

std::cout<<"\n\n";
vec2.clear();

vec2.push_back(100);
vec2.push_back(200);

for (std::size_t i = 0; i < vec2.size(); ++i)
{
int* val = &ptr2[i];
std::cout<<*val<<"\n";
}
}

Этот распределитель гарантирует, что вся память выделена по указанному адресу. Вы можете выделить не более указанной вами суммы со свободой выделения, если вы хотите, находится ли она в стеке или в куче.

Вы можете создать свой собственный пул или использовать std::unique_ptr в качестве пула для одного контейнера.

РЕДАКТИРОВАТЬ: Для строк вам нужно смещение sizeof(_Rep_base), Увидеть: Почему std :: string выделяется дважды?

а также http://ideone.com/QWtxWg

Он определяется как:

struct _Rep_base
{
std::size_t     _M_length;
std::size_t     _M_capacity;
_Atomic_word        _M_refcount;
};

Итак, пример становится:

struct Repbase
{
std::size_t     length;
std::size_t     capacity;
std::int16_t    refcount;
};

int main()
{
typedef std::basic_string<char, std::char_traits<char>, CAllocator<char>> CAString;

const int size = 1024;
char ptr[size] = {0};

CAString str(CAllocator<char>(&ptr[0], size));
str = "Hello";

std::cout<<&ptr[sizeof(Repbase)];
}
4

Другие решения

Использование std :: map вводит много дополнительного синтаксиса … который может сбивать с толку … пока не повезло
Я не могу легко определить, что я делаю неправильно. Попытка пока:

typedef CAllocator<std::pair<const int, char>> pair_alloc;

void test_allocator_with_map()
{
const int size=2048;
std::pair<int, char> mem[size];

//auto dummy = pair_alloc(mem[0],size); //the problem seems to be my cStor parameters... this also fail

std::map<int,char,std::less<int>,pair_alloc> myMap1(pair_alloc(mem[0],size));
myMap1[4]='l';
std::cout<< myMap1[4] << "\n";
};

//signature of std::map
// <typename _Key,
// typename _Tp,
// typename _Compare = std::less<_Key>,
// typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
// std::pair<const _Key, _Tp>

Я думаю, что первый шаг, скорее, должен написать шаблон, который перенаправляет параметры в шаблон std :: map

0

По вопросам рекламы [email protected]