0

我想创建一个对象池,但我希望它只在我的内存堆的特定段上分配内存。有没有办法使用 boost 来做到这一点?

4

1 回答 1

3

Boost.Poolobject_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()都在 arena 的内存范围内。此外,当b通过 释放时pool.free(b),内存 ( ) 在下一次for0x804b5a4时立即被池重用。malloc()c

于 2013-11-07T19:08:53.507 回答