Boost logo

Boost Users :

From: Flogromp N. (looseonthestreet_at_[hidden])
Date: 2007-12-13 22:19:24


/*

The pool allocator is not being used properly, somehow, with std::list.
When you go to purge the pool, it says nothing was purged, because nothing
is even registered as being allocated in the pool.
What is going on here?
I have included copious debugging information. I've even provided a dummy
modification of the boost::pool_allocator class to show what's going on.
It's weird. If you change l_type to an std::vector, everything will work,
and the output will be: purged? 1

This program outputs the following when l_type is std::list,

debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::debug_pool_allocator() [with Tag = foo_tag, T = int,
UserAllocator = boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::debug_pool_allocator(const debug_pool_allocator<Tag, U,
UserAllocator, Mutex, NextSize>&) [with U = int, Tag = foo_tag, T =
std::_List_node<int>, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
static T* debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::allocate(typename boost::pool<UserAllocator>::size_type) [with
Tag = foo_tag, T = std::_List_node<int>, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]

---
static T* debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::allocate(typename boost::pool<UserAllocator>::size_type) [with
Tag = foo_tag, T = std::_List_node<int>, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
---
...
purged? 0
released? 0
This program outputs the following when l_type is std::vector,
debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::debug_pool_allocator() [with Tag = foo_tag, T = int,
UserAllocator = boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
static T* debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::allocate(typename boost::pool<UserAllocator>::size_type) [with
Tag = foo_tag, T = int, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
---
static T* debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::allocate(typename boost::pool<UserAllocator>::size_type) [with
Tag = foo_tag, T = int, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
static void debug_pool_allocator<Tag, T, UserAllocator, Mutex,
NextSize>::deallocate(T*, typename boost::pool<UserAllocator>::size_type)
[with Tag = foo_tag, T = int, UserAllocator =
boost::default_user_allocator_new_delete, Mutex =
boost::details::pool::default_mutex, unsigned int NextSize = 32u]
---
...
purged? 1
released? 0
*/
#include <iostream>
using std::cout;
using std::endl;
#include <list>
#include <vector>
#include <boost/current_function.hpp>
#include <boost/limits.hpp>
// std::numeric_limits
#include <new>
// std::bad_alloc
#include <boost/pool/poolfwd.hpp>
#include <boost/pool/singleton_pool.hpp>
#include <boost/pool/pool_alloc.hpp>
#define DEBUG_FUNC cout << BOOST_CURRENT_FUNCTION << " " << endl
template <
    class Tag,
    class T,
    class UserAllocator = boost::default_user_allocator_new_delete,
    class Mutex = boost::details::pool::default_mutex,
    unsigned NextSize = 32
>
class debug_pool_allocator
{
  public:
    typedef T value_type;
    typedef UserAllocator user_allocator;
    typedef Mutex mutex;
    static unsigned const next_size = NextSize;
    typedef value_type* pointer;
    typedef value_type const* const_pointer;
    typedef value_type& reference;
    typedef value_type const& const_reference;
    typedef typename boost::pool<UserAllocator>::size_type size_type;
    typedef typename boost::pool<UserAllocator>::difference_type
difference_type;
    template <class U>
    struct rebind {
        typedef debug_pool_allocator<Tag, U, UserAllocator, Mutex, NextSize>
other;
    };
    debug_pool_allocator() {
        DEBUG_FUNC;
    }
    // default copy constructor
    // default assignment operator
    // not explicit, mimicking std::allocator [20.4.1]
    template <class U>
    debug_pool_allocator(
        debug_pool_allocator<Tag, U, UserAllocator, Mutex, NextSize> const&
    ) {
        DEBUG_FUNC;
    }
    // default destructor
    static pointer address(reference r) {
        DEBUG_FUNC;
        return &r;
    }
    static const_pointer address(const_reference s) {
        DEBUG_FUNC;
        return &s;
    }
    static size_type max_size() {
        DEBUG_FUNC;
        return (std::numeric_limits<size_type>::max)();
    }
    static void construct(pointer const ptr, value_type const& t) {
        DEBUG_FUNC;
        new(ptr) T(t);
    }
    static void destroy(pointer const ptr) {
        DEBUG_FUNC;
        ptr->~T();
    }
    bool operator==(debug_pool_allocator const&) const {
        DEBUG_FUNC;
        return true;
    }
    bool operator!=(debug_pool_allocator const&) const {
        DEBUG_FUNC;
        return false;
    }
    static pointer allocate(size_type const n) {
        DEBUG_FUNC;
        const pointer ret =
            static_cast<pointer>(
                boost::singleton_pool<
                    Tag, sizeof(T), UserAllocator, Mutex, NextSize
                >::ordered_malloc(n)
            )
        ;
        if (ret == 0)
            throw std::bad_alloc();
        return ret;
    }
    static pointer allocate(size_type const n, void const* const) {
        DEBUG_FUNC;
        return allocate(n);
    }
    static void deallocate(pointer const ptr, size_type const n) {
        DEBUG_FUNC;
        boost::singleton_pool<
            Tag, sizeof(T), UserAllocator, Mutex, NextSize
        >::ordered_free(ptr, n);
    }
};
// ---
struct foo_tag {};
// IF YOU CHANGE THIS TO std::vector, IT WILL DEALLOCATE PROPERLY!
typedef std::list<
    int,
    debug_pool_allocator<foo_tag, int>
> l_type;
int main()
{
    bool success = false;
    l_type* l = new l_type;
    for (int i=0; i<2; ++i) {
        l->push_back(444);
        cout << "---" << endl;
    }
    cout << "..." << endl;
    success = boost::singleton_pool<foo_tag, sizeof(int)>::purge_memory();
    cout << "purged? " << success << endl;
    success = boost::singleton_pool<foo_tag, sizeof(int)>::release_memory();
    cout << "released? " << success << endl;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net