|
Boost : |
From: scleary_at_[hidden]
Date: 2001-05-03 09:15:07
> A cursory search of boost has not yielded information
> I need on how to create a maximally aligned integer.
>
> Specifically, given a positive integer n, I need to find
> an integer m, such that p+m is maximally aligned, where
> p is maximally aligned.
As John Maddock said, I don't think it's possible to find this value
directly.
> This calculation is required for ALL code which suballocates
> memory for indeterminate types. My particular problem is
> a garbage collector, which chains allocated blocks together:
> the pointers of the chain are stored in a 'block header'
> before the address returned to the user. I need to know
> how big to make that header.
What I used to guarantee Pool alignment was a side-stepping of this issue,
so I didn't have to calculate the "maximally aligned integer"; what I
actually use is an integer type that guarantees alignment only for a few
well-defined types (the user-specified allocation size, a pointer for the
free list, and std::size_t for the block sizes) -- not *any* type. For
details, see:
http://www.boost.org/libs/pool/doc/implementation/alignment.html
But note that my solution is able to side-step this issue because Pool
doesn't keep *any* information about allocated chunks. Your problem can use
a similar solution, but only if you go to a footer instead of a header,
which requires you to store additional data in the footer (size of block or
pointer to block) -- but if you already wanted to store this data, then the
following would be ok:
class allocated_chain
{
private:
void * list;
public:
void * allocate(std::size_t size)
{
const std::size_t size_usable_by_process = lcm(sizeof(void *), size);
const std::size_t size_to_allocate = size_usable_by_process +
2*sizeof(void *);
char * const block = new char[size_to_allocate];
// The Standard mandates that "block" is aligned for *any* type T
where
// sizeof(T) <= size_to_allocate
// Also, note that "block + size_usable_by_process" is aligned for
"void *"
// Each block contains a pointer to itself
char * const block_ptr_in_block = block + size_usable_by_process;
*((void **) block_ptr_in_block) = block;
// And a pointer into the next block
char * const next_ptr_in_block = block_ptr_in_block + sizeof(void *);
*((void **) next_ptr_in_block) = list;
list = (void *) next_ptr_in_block;
return (void *) block;
}
};
If you don't want that overhead, you'll have to guess at the maximally
aligned integer, using what John suggested. AFAICT, those are your only
options.
-Steve
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk