I would like to create an object pool but I want it to allocate memory on only a specific segment of my memory heap. Is there any way to do so using boost ?
1 Answers
Boost.Pool's object_pool
allows the user to control the memory used by the pool by providing a UserAllocator
. Per the documentation:
Pool objects need to request memory blocks from the system, which the Pool then splits into chunks to allocate to the user. By specifying a
UserAllocator
template parameter to various Pool interfaces, users can control how those system memory blocks are allocated.
Boost.Pool only provides basic allocators that use new/delete
and malloc/free
. However, if an allocator can be written to allocate in specific segments of the free store, then object_pool
can be configured to do so as well. It may be necessary to check if the compiler and platform supports limiting allocations within the free store to a specific segment.
Here is a basic example where I have ignored some of the details to keep the example simple, and show how a type can meet the requirements for UserAllocator
. In this example, boost::object_pool
will use a custom allocator that uses pre-allocated static memory.
#include <iostream>
#include <boost/array.hpp>
#include <boost/pool/object_pool.hpp>
namespace detail {
/// @brief Pre-allocated managed memory block.
template <std::size_t N>
class arena
{
public:
/// @brief Constructor.
arena()
: current_(&buffer_.front()), // Set current to start.
end_(current_ + N) // End sentinel.
{
std::cout << "arena memory range: "
<< static_cast<void*>(current_) << " - "
<< static_cast<const void*>(end_) << std::endl;
}
/// @brief Attempt to allocate memory from pre-allocated block.
///
/// @param n Count of bytes to allocate.
///
/// @param Non-zero if allocation is succesfull. Otherwise, zero.
char* allocate(std::size_t n)
{
// If there is no more memory, then return zero.
if ((current_ + n) > end_) return 0;
// Otherwise, return available memory and shift current.
std::cout << "arena allocating: "
<< static_cast<void*>(current_) << std::endl;
char* ptr = current_;
current_ += n;
return ptr;
}
void deallocate(char* p, std::size_t n)
{
// ...
}
private:
/// @brief Block of memory used for allocations.
boost::array<char, N> buffer_;
/// @brief Pointer to current allocation.
char* current_;
//// @brief End pointer sentinel.
const char* end_;
};
} // namespace detail
/// @brief Allocator that meets Boost.Pool's UserAllocator Concepts.
/// This allocator will allocate memory from a pre-allocated
/// block of static memory. Each instance of the template is
/// considered to be its own unique allocator, and thus has its
/// own memory.
template <std::size_t N>
class static_allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char* malloc(const size_type n) { return arena_.allocate(n); }
static void free(char* p) { arena_.deallocate(p, 1); }
private:
static detail::arena<N> arena_;
};
template <std::size_t N>
detail::arena<N> static_allocator<N>::arena_;
/// @brief Helper type.
template <typename T, std::size_t N>
struct static_object_pool:
boost::object_pool<T, static_allocator<N * sizeof(T)> >
{};
/// Mockup object.
class Foo {};
int main()
{
static_object_pool<Foo, 128> pool;
Foo* a = pool.malloc();
std::cout << "a is at " << a << std::endl;
Foo* b = pool.malloc();
std::cout << "b is at " << b << " -- freeing b" << std::endl;
pool.free(b);
Foo* c = pool.malloc();
std::cout << "c is at " << c << std::endl;
}
And the output:
arena memory range: 0x804b5a0 - 0x804b620
arena allocating: 0x804b5a0
a is at 0x804b5a0
b is at 0x804b5a4 -- freeing b
c is at 0x804b5a4
Note that each address returned from object_pool::malloc()
is within the arena's memory range. Additionally, when b
was freed via pool.free(b)
, the memory (0x804b5a4
) was immediately reused by the pool upon next malloc()
for c
.

- 51,153
- 9
- 112
- 169
-
1an example how to use it would be really helpful – w00d Nov 07 '13 at 23:35
-
@w00d: I added an example of how to meet the type requirements for `UserAllocator`. I also expanded slightly on the answer, as it was initially unclear to me as whether the question was asking about controlling how Boost.Pool allocates or the actual allocation itself. For what it is worth, I have only been able to allocate to specific segments in the free store on fixed address embedded systems using implementation specific calls. – Tanner Sansbury Nov 15 '13 at 16:43