/*

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;
}