I'm using boost.pool, but I don't know when to use boost::pool<>::malloc
and boost::pool<>::ordered_malloc
?
so,
what's the difference of
boost::pool<>::malloc
andboost::pool<>::ordered_malloc
?when should I use
boost::pool<>::ordered_malloc
?
I'm using boost.pool, but I don't know when to use boost::pool<>::malloc
and boost::pool<>::ordered_malloc
?
so,
what's the difference of boost::pool<>::malloc
and boost::pool<>::ordered_malloc
?
when should I use boost::pool<>::ordered_malloc
?
First, we should know the basic idea behind the Boost Pool library:
simple_segregated_storage
, it is similar to a singly linked list, and responsible for partitioning a memory block into fixed-size chunks:A memory pool keeps a free list of memory chunks. So we mentioned blocks and chunks: the memory pool uses
new
ormalloc
to allocate a memory block and divides it into many memory chunks which have same size.Assume the address is aligned by 8, 4 bytes for storing the address of next chunk, so a memory block(8 bytes * 32 chunks) is as below(the memory address is just for illustrating the question, not a real one):
Now, suppose the user allocates 8 bytes memory twice, so the chunks: [0xDD00,0xDD08), [0xDD08,0xDD10) are used. After a while, the user releases the memory at [0xDD00,0xDD08), so this chunk will go back to the free list. Now the block is like this:
Afterwards the user releases the memory at [0xDD08,0xDD10), the simplest way to place this chunk back in the list is to update the
first
to point to it, constant time complexity. thesimple_segregated_storage<T>::free()
is doing this exactly:After that, the list would be like this:
Now we noticed the list of chunks are not ordered by their address after these operations! If we want to preserve the order while de-allocating, call
pool<>::ordered_free()
instead ofpool<>::free()
to places the memory back in the list in its proper order. Now we've known what's the order in the memory pool, let's dig into the source code ofboost::pool<>::malloc
andboost::pool<>::ordered_malloc
:As we can see, they differ only when there is no free chunk in the list of memory blocks. In this scenario, it allocates a new memory block, merges its free list to pool's free list, the difference between these two methods is that
boost::pool<>::ordered_malloc
preserves order while merging the free lists.Above is for question 1.
So, why does the order matter?! It seems the memory pool works perfectly with the unordered chunks!
First, if we want to find a contiguous sequence of n chunks, the ordered free list would make it easier. Second, Let's have a look at the derived class of
boost::pool
:boost::object_pool
, it provides automatic destruction of non-deallocated objects on destruction of theobject_pool
object while you can also destroy the object manually, for example:the code above is OK, no memory leak or double delete! How does
boost::object_pool
do this magic? Let's find the implementation of destructor ofboost::object_pool
(I have boost 1.48 on my machine):it goes through all the chunks in the list of memory blocks(
list
, the data member ofboost::pool<>
, holds the locations and sizes of all memory blocks allocated from the system) to find whether any chunk in it also shows in the free list, if not, calls the destructor of the object, then free the memory. So it's kind of getting the intersection of two sets, just as std::set_intersection() does! If the list is sorted, it would be much faster to do that. Actually in theboost::object_pool<>
, the order is required, the public member functions:boost::object_pool<>::malloc()
andboost::object_pool<>::free()
just call theboost::pool<>::ordered_malloc()
andboost::pool<>::ordered_free()
respectively:So for the queston 2: You needn't use
boost::pool<>::ordered_malloc
in most situations.