By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,075 Members | 957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,075 IT Pros & Developers. It's quick & easy.

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

P: n/a
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

Jul 10 '07 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On 10 Jul, 03:37, Barry <dhb2...@gmail.comwrote:
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


Jul 10 '07 #2

P: n/a
On 7 10 , 8 44 , dasjotre <dasjo...@googlemail.comwrote:
On 10 Jul, 03:37, Barry <dhb2...@gmail.comwrote:
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
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<Tconst&) : pool_allocator<T>()
{}
my_pool_allocator(pool_allocator<Tconst&) {}

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

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

Jul 10 '07 #3

P: n/a
On 10 Jul, 16:09, Barry <dhb2...@gmail.comwrote:
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<Tconst&) : pool_allocator<T>()
{}
my_pool_allocator(pool_allocator<Tconst&) {}

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

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
my_pool_allocator<int>
instance at all.
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.
Thanks
regards

DS

Jul 10 '07 #4

This discussion thread is closed

Replies have been disabled for this discussion.