升压池最大尺寸 [英] Boost Pool maximum size

查看:276
本文介绍了升压池最大尺寸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用升压池静态存储器供应商,

I am using boost pool as a static memory provider,

void func()
{
  std::vector<int, boost::pool_allocator<int> > v;
  for (int i = 0; i < 10000; ++i)
    v.push_back(13);
}

在上面code,我们如何解决池的大小,我的意思是我们所知道的boost ::池提供为静态内存分配,但我不能够解决这个池的大小,它保持生长,应该有办法来限制其大小。
例如我要200块池只有这样我就可以拿200块后,它应该NULL,虽然
请让我现在该怎么办这个

In above code, how we can fix the size of pool, i mean as we know boost::pool provide as a static memory allocator, but i am not able to fix the size of this pool, its keep growing, there should be way to restrict its size. for example i want a pool of 200 chunks only so i can take 200 chunks after that it should though NULL please let me now how to do this

推荐答案

我不认为提振池提供你想要什么。其实有对的boost :: pool_allocator 除对象的类型4其他模板参数:

I don't think boost pool provides what you want. Actually there are 4 other template parameters for boost::pool_allocator except the type of object:


  • UserAllocator :定义底层池将使用从系统(默认值= 的boost :: default_user_allocator_new_delete )。

  • 互斥:允许用户确定同步类型要在底层singleton_pool(默认值= 的boost ::细节::池使用:: default_mutex )。

  • NextSize :这个参数的值传递给底层池创建并指定块在第一分配请求分配数时(默认值= 32 )。

  • MAXSIZE :这个参数的值传递给底层池创建并指定块中的任何一个分配请求分配的(最大数量默认,当它= 0)。

  • UserAllocator: Defines the method that the underlying Pool will use to allocate memory from the system(default = boost::default_user_allocator_new_delete).
  • Mutex: Allows the user to determine the type of synchronization to be used on the underlying singleton_pool(default = boost::details::pool::default_mutex).
  • NextSize: The value of this parameter is passed to the underlying Pool when it is created and specifies the number of chunks to allocate in the first allocation request (default = 32).
  • MaxSize: The value of this parameter is passed to the underlying Pool when it is created and specifies the maximum number of chunks to allocate in any single allocation request (default = 0).

您可能会认为 MAXSIZE 是你想要什么,但不幸的是事实并非如此。
的boost :: pool_allocator 使用基本的boost :: singleton_pool 这是基于一个升压: :池 MAXSIZE 最终会传递给的boost ::池&LT的数据成员;&GT; 的max_size ,所以什么作用的的max_size 提振起到::池?让我们来看看的boost ::池::的malloc()

You may think MaxSize is exactly what you want, but unfortunately it's not. boost::pool_allocator uses a underlying boost::singleton_pool which is based on an boost::pool, the MaxSize will eventually pass to the data member of boost::pool<>: max_size, so what role does the max_size play in the boost::pool? let's have a look at boost::pool::malloc():

void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
{ //! Allocates a chunk of memory. Searches in the list of memory blocks
  //! for a block that has a free chunk, and returns that free chunk if found.
  //! Otherwise, creates a new memory block, adds its free list to pool's free list,
  //! \returns a free chunk from that block.
  //! If a new memory block cannot be allocated, returns 0. Amortized O(1).
  // Look for a non-empty storage
  if (!store().empty())
    return (store().malloc)();
  return malloc_need_resize();
}

显然, 的boost ::池立即分配一个新的内存块,如果在内存块可用的自由块。让我们继续深入到 malloc_need_resize()

Obviously, boost::pool immediately allocates a new memory block if no free chunk available in the memory block. Let's continue to dig into the malloc_need_resize():

template <typename UserAllocator>
void * pool<UserAllocator>::malloc_need_resize()
{ //! No memory in any of our storages; make a new storage,
  //!  Allocates chunk in newly malloc aftert resize.
  //! \returns pointer to chunk.
  size_type partition_size = alloc_size();
  size_type POD_size = static_cast<size_type>(next_size * partition_size +
      math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
  char * ptr = (UserAllocator::malloc)(POD_size);
  if (ptr == 0)
  {
     if(next_size > 4)
     {
        next_size >>= 1;
        partition_size = alloc_size();
        POD_size = static_cast<size_type>(next_size * partition_size +
            math::static_lcm<sizeof(size_type), sizeof(void *)>::value + sizeof(size_type));
        ptr = (UserAllocator::malloc)(POD_size);
     }
     if(ptr == 0)
        return 0;
  }
  const details::PODptr<size_type> node(ptr, POD_size);

  BOOST_USING_STD_MIN();
  if(!max_size)
    next_size <<= 1;
  else if( next_size*partition_size/requested_size < max_size)
    next_size = min BOOST_PREVENT_MACRO_SUBSTITUTION(next_size << 1, max_size*requested_size/ partition_size);

  //  initialize it,
  store().add_block(node.begin(), node.element_size(), partition_size);

  //  insert it into the list,
  node.next(list);
  list = node;

  //  and return a chunk from it.
  return (store().malloc)();
}

我们可以从源头code看到, 的max_size 只是涉及块从系统下一次请求的数量,我们只能放慢通过这个参数来提高速度。结果
但是请注意,我们可以定义底层池将使用从系统分配内存,如果我们限制的内存从系统分配的大小,池的大小不会保持增长的方法。在这个这样,的boost ::池似乎是多余的,可以直接通过自定义分配器的STL容器。这是自定义分配器的其中分配内存为例(在此基础上链接)从堆到一个给定的尺寸:

As we can see from the source code, max_size is just related to the number of chunks to request from the system next time, we can only slow down the speed of increasing via this parameter.
But notice that we can defines the method that the underlying pool will use to allocate memory from the system, if we restrict the size of memory allocated from system, the pool's size wouldn't keep growing. In this way, boost::pool seems superfluous, you can pass the custom allocator to STL container directly. Here is a example of custom allocator(based on this link) which allocates memory from stack up to a given size:

#include <cassert>
#include <iostream>
#include <vector>
#include <new>

template <std::size_t N>
class arena
{
    static const std::size_t alignment = 8;
    alignas(alignment) char buf_[N];
    char* ptr_;

    bool
        pointer_in_buffer(char* p) noexcept
    { return buf_ <= p && p <= buf_ + N; }

public:
    arena() noexcept : ptr_(buf_) {}
    ~arena() { ptr_ = nullptr; }
    arena(const arena&) = delete;
    arena& operator=(const arena&) = delete;

    char* allocate(std::size_t n);
    void deallocate(char* p, std::size_t n) noexcept;

    static constexpr std::size_t size() { return N; }
    std::size_t used() const { return static_cast<std::size_t>(ptr_ - buf_); }
    void reset() { ptr_ = buf_; }
};

template <std::size_t N>
char*
arena<N>::allocate(std::size_t n)
{
    assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
    if (buf_ + N - ptr_ >= n)
    {
        char* r = ptr_;
        ptr_ += n;
        return r;
    }
    std::cout << "no memory available!\n";
    return NULL;
}

template <std::size_t N>
void
arena<N>::deallocate(char* p, std::size_t n) noexcept
{
    assert(pointer_in_buffer(ptr_) && "short_alloc has outlived arena");
    if (pointer_in_buffer(p))
    {
        if (p + n == ptr_)
            ptr_ = p;
    }
}

template <class T, std::size_t N>
class short_alloc
{
    arena<N>& a_;
public:
    typedef T value_type;

public:
    template <class _Up> struct rebind { typedef short_alloc<_Up, N> other; };

    short_alloc(arena<N>& a) noexcept : a_(a) {}
    template <class U>
    short_alloc(const short_alloc<U, N>& a) noexcept
        : a_(a.a_) {}
    short_alloc(const short_alloc&) = default;
    short_alloc& operator=(const short_alloc&) = delete;

    T* allocate(std::size_t n)
    {
        return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
    }
    void deallocate(T* p, std::size_t n) noexcept
    {
        a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
    }

    template <class T1, std::size_t N1, class U, std::size_t M>
    friend
        bool
        operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) noexcept;

    template <class U, std::size_t M> friend class short_alloc;
};

template <class T, std::size_t N, class U, std::size_t M>
inline
bool
operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
{
    return N == M && &x.a_ == &y.a_;
}

template <class T, std::size_t N, class U, std::size_t M>
inline
bool
operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) noexcept
{
    return !(x == y);
}


int main()
{
    const unsigned N = 1024;
    typedef short_alloc<int, N> Alloc;
    typedef std::vector<int, Alloc> SmallVector;
    arena<N> a;
    SmallVector v{ Alloc(a) };
    for (int i = 0; i < 400; ++i)
    {
        v.push_back(10);
    }

}

这篇关于升压池最大尺寸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆