Experience with using the Boost Pool is required. Is this useful as a pre-distribution valve?

I recently searched for a pool / allocator mechanism. The Boost Pool seems to provide a solution, but there are still things that he could not deduce from the documentation.

What to highlight

  • Several small classes (~ 30 characters)
  • std :: map (I want it to not execute the dynamic allocator by itself)
  • distribution inside pugi :: xml
  • std :: strings

How to manage the address space to host (or just the amount)

Object_pool seems to provide a good way to highlight the need 1) However, he would like to set a fixed size for use by the dispenser. By default, it captures memory. If possible, I would like to tell him the address space in which he can play.

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

or

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

Although UserAllocator is available in Boost :: Pool; he seems to be defeating the point. I am afraid that the necessary control will make it too inefficient ... and it would be better to start from scratch.

Is it possible to set a fixed area for pool_allocator?

The question is a bit like the first. Pool amplification provides any way to limit how much / where memory is allocated when adding boost :: pool_allocator to a std-type class (for example, a map)

My script

Built-in linux programming. The system should continue to work. Therefore, we cannot risk segmentation of memory. Currently, I basically either have a static distribution (stack), but also a few initial "new" ones. I would like the distribution scheme to ensure that I use the same memory area every time the program loops. Speed ​​/ space is important, but safety is still a top priority.

I hope StackOverflow is the place to ask. I tried contacting the author of Boost :: Pool "Stephen" without any luck. I did not find a Boost forum.

+6
source share
2 answers

You can always create a dispenser that works with STL. If it works with STL, it should work with boost, since you can pass gain distributors to STL containers.

Considering the above, a distributor that can allocate to a specified memory address AND has a size limit specified by you can be written as follows:

 #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"; } } 

This allocator ensures that all memory is allocated to the specified address. No more than what you specify, the freedom of allocation can be allocated if you want whether it is on the stack or heap.

You can create your own pool or use std::unique_ptr as a pool for one container.

EDIT: For strings, you will need a sizeof(_Rep_base) offset sizeof(_Rep_base) . See Why is std :: string highlighting twice?

and http://ideone.com/QWtxWg

It is defined as:

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

So, an example would look like this:

 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
source

Using std :: map represents a lot of extra syntax ... which can be confusing ... until it succeeds. I can't figure out what I'm doing wrong. Trying so far:

 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> 

I assume that the first step should be to write a template that passes parameters to the std :: map template

0
source

All Articles