オブジェクト プールを作成したいのですが、メモリ ヒープの特定のセグメントだけにメモリを割り当てたいです。boost を使用してこれを行う方法はありますか?
1 に答える
Boost.Pool をobject_pool
使用すると、ユーザーはUserAllocator
. ドキュメントごと:
プール オブジェクトはシステムからメモリ ブロックを要求する必要があり、プールはそれをチャンクに分割してユーザーに割り当てます。テンプレート パラメーターをさまざまな Pool インターフェイスに指定することにより
UserAllocator
、ユーザーはこれらのシステム メモリ ブロックの割り当て方法を制御できます。
Boost.Pool は、new/delete
とを使用する基本的なアロケータのみを提供しますmalloc/free
。ただし、フリー ストアの特定のセグメントに割り当てるようにアロケータを記述できる場合は、そのobject_pool
ように構成することもできます。コンパイラとプラットフォームが、フリー ストア内の割り当てを特定のセグメントに制限することをサポートしているかどうかを確認する必要がある場合があります。
これは、例を単純にするために詳細の一部を無視した基本的な例であり、型が の要件をどのように満たすことができるかを示していますUserAllocator
。この例でboost::object_pool
は、事前に割り当てられた静的メモリを使用するカスタム アロケーターを使用します。
#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;
}
そして出力:
arena memory range: 0x804b5a0 - 0x804b620
arena allocating: 0x804b5a0
a is at 0x804b5a0
b is at 0x804b5a4 -- freeing b
c is at 0x804b5a4
から返される各アドレスはobject_pool::malloc()
、アリーナのメモリ範囲内にあることに注意してください。さらに、b
が によって解放されたときpool.free(b)
、メモリ ( ) は次の0x804b5a4
のプールによってすぐに再利用されました。malloc()
c