boost::singleton_pool<...>::release_memory problem

B

Barry

As boost::pool_alloc use singleton holder for pool allocator, client
programmers have to reclaim the memory by hand through calling
singleton_pool<alloc_tag, elem_size>::purge_memory() or something to
release the memory, so the program should have knowledge of the
elem_size, sometime, it's impossible or at least hard to know the size
of the element allocated by the allocator.
for example:
struct my_tag
list<int, boost::pool_allocator<int> > List;
.....
boost::singleton_pool<boost::pool_allocator_tag,
sizeof(_List_node)>::release_memory()

Here _List_node is the real element that is dynamic created by
allocator, so if I use sizeof(int) instead, it does NOT work
 
D

dasjotre

As boost::pool_alloc use singleton holder for pool allocator, client
programmers have to reclaim the memory by hand through calling
singleton_pool<alloc_tag, elem_size>::purge_memory() or something to
release the memory, so the program should have knowledge of the
elem_size, sometime, it's impossible or at least hard to know the size
of the element allocated by the allocator.
for example:
struct my_tag
list<int, boost::pool_allocator<int> > List;
....
boost::singleton_pool<boost::pool_allocator_tag,
sizeof(_List_node)>::release_memory()

Here _List_node is the real element that is dynamic created by
allocator, so if I use sizeof(int) instead, it does NOT work

indeed, list uses rebind mechanism to define allocator to use.
_List_node is implementation detail and you should not use it.

I don't think there is a way to achieve that other than to extend
pool_allocator

something like
template <class T, ...>
class my_pool_allocator : public boost::pool_allocator<T, ...>
{
... forward constructors here

// rebind
template <typename U>
struct rebind
{
typedef my_pool_allocator<U, ...> other;
};

bool release_memory() const
{
return ::boost::singleton_pool
< ::boost::pool_allocator_tag
, sizeof(T)
...
>::release_memory();
}
};

std::list<int, my_pool_allocator<int, ...> > list;
list.get_allocator().release_memory()


regards

DS
 
B

Barry

indeed, list uses rebind mechanism to define allocator to use.
_List_node is implementation detail and you should not use it.

I don't think there is a way to achieve that other than to extend
pool_allocator

something like
template <class T, ...>
class my_pool_allocator : public boost::pool_allocator<T, ...>
{
.. forward constructors here

// rebind
template <typename U>
struct rebind
{
typedef my_pool_allocator<U, ...> other;
};

bool release_memory() const
{
return ::boost::singleton_pool
< ::boost::pool_allocator_tag
, sizeof(T)
...
}

};

std::list<int, my_pool_allocator<int, ...> > list;
list.get_allocator().release_memory()

regards

DS

As check out SGI and Dimkumware STL implementation, I found that they
neither rebind the XX_node(something like that) to be their
allocator_type, they separately provide _Buynod and _M_get_node to
create a node,

So the following code below in MSVC 8.0:

template <class T>
struct my_pool_allocator : pool_allocator<T> {
my_pool_allocator() : pool_allocator<T>() {}
my_pool_allocator(my_pool_allocator<T> const&) : pool_allocator<T>()
{}
my_pool_allocator(pool_allocator<T> const&) {}

template <class U>
struct rebind {
typedef my_pool_allocator<U> other;
};

static bool release_memory()
{
return singleton_pool
< pool_allocator_tag
, sizeof(T)
>::release_memory();
}

};

int main(int argc, char* argv[])
{
typedef list<int, my_pool_allocator<int> > mylist;
mylist IntList;
cout << typeid(IntList.get_allocator()).name() << endl;
return 0;
}

produces the result:
struct my_pool_allocator<int>
and it really does not reclaim memory as I walk into the function

I don't konw the my_pool_allocator extension is right or not, but I
think it does not affect the result

So, if the container is not vector, it's hard to use
boost::pool_allocator and release_memory, if not hopeless

Thanks
 
D

dasjotre

As check out SGI and Dimkumware STL implementation, I found that they
neither rebind the XX_node(something like that) to be their
allocator_type, they separately provide _Buynod and _M_get_node to
create a node,

So the following code below in MSVC 8.0:

template <class T>
struct my_pool_allocator : pool_allocator<T> {
my_pool_allocator() : pool_allocator<T>() {}
my_pool_allocator(my_pool_allocator<T> const&) : pool_allocator<T>()
{}
my_pool_allocator(pool_allocator<T> const&) {}

template <class U>
struct rebind {
typedef my_pool_allocator<U> other;
};

static bool release_memory()
{
return singleton_pool
< pool_allocator_tag
, sizeof(T)
::release_memory();
}

};

int main(int argc, char* argv[])
{
typedef list<int, my_pool_allocator<int> > mylist;
mylist IntList;
cout << typeid(IntList.get_allocator()).name() << endl;
return 0;

}

produces the result:
struct my_pool_allocator<int>
and it really does not reclaim memory as I walk into the function

yes, I tried it too. VC8 list actually doesn't use
I don't konw the my_pool_allocator extension is right or not, but I
think it does not affect the result

So, if the container is not vector, it's hard to use
boost::pool_allocator and release_memory, if not hopeless

I agree, even worse, pool allocation is unsuitable
for continuous storage requirements.

according to the standard [23.8] all container's memory
allocation have to come from an instance of allocator
whose value type is the same as the container's value type.
not possible for most containers.

just looking at std::allocator,

template<class _Other>
allocator(const allocator<_Other>&)
{ // construct from a related allocator (do nothing)
}

hints how broken the design is

if the container is using my_pool_allocator rebind
for any additional allocators you could put
release_memory() into my_pool_allocator destructor.

regards

DS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,291
Messages
2,571,453
Members
48,137
Latest member
IndiraMcCo

Latest Threads

Top