BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_alignmentutil

Typedefs

typedef bsls::AlignmentUtil bsls_AlignmentUtil
 This alias is defined for backward compatibility.
 

Detailed Description

Outline

Purpose

Provide constants, types, and operations related to alignment.

Classes

See also
bslma_bufferimputil

Description

This component defines a struct, bsls::AlignmentUtil, which serves as a namespace for compile-time constants, types, and operations associated with alignment on the current platform.

The BSLS_MAX_ALIGNMENT enumerator provides the minimal value that satisfies the alignment requirements for all types on the current platform. Additionally, the MaxAlignedType typedef specifies a primitive type that requires an alignment of BSLS_MAX_ALIGNMENT.

The calculateAlignmentFromSize function calculates a usable (but not necessarily minimal) alignment for any object with a memory footprint of the specified size (in bytes). The calculateAlignmentOffset function calculates the offset from a specified address where an object having a specified alignment requirement can be constructed safely. The is2ByteAligned, is4ByteAligned, and is8ByteAligned functions each return true if a specified address is, respectively, 2-, 4-, or 8-byte aligned. Finally, roundUpToMaximalAlignment returns the smallest whole multiple of BSLS_MAX_ALIGNMENT greater than or equal to its argument.

Assumptions

The functionality in this component makes several assumptions:

Usage

A sequential memory allocator is used to return a sequence of memory blocks of varying requested sizes from a larger chunk of contiguous memory. Each block returned must also have an alignment that is sufficient for any conceivable object of that size. To achieve a fully factored implementation, we might choose to provide a low-level helper function naturallyAlign that, given the address of the next available byte in the larger chunk along with the requested block size (in bytes), returns the first appropriately (or naturally) aligned address for the requested block at or after address:

void *naturallyAlign(void **currentAddress, int size);
// Return the closest memory address at or after the specified
// '*currentAddress' that is sufficiently aligned to accommodate any
// object of the specified 'size', and update '*currentAddress' to
// refer to the first available byte after the allocated object. The
// behavior is undefined unless '1 <= size'.

We can implement the naturallyAlign helper function easily using the methods defined in this class:

void *naturallyAlign(void **currentAddress, std::size_t size)
{
size);
*currentAddress,
alignment);
char *result = static_cast<char *>(*currentAddress) + offset;
*currentAddress = result + size;
return result;
}
static int calculateAlignmentOffset(const void *address, int alignment)
Definition bsls_alignmentutil.h:408
static int calculateAlignmentFromSize(std::size_t size)
Definition bsls_alignmentutil.h:344

We will then be able to use this naturallyAlign helper function to allocate, from a buffer of contiguous memory, efficiently (but not necessarily optimally) aligned memory for objects of varying sizes based solely on the size of each object (i.e., determined by its natural, not actual, alignment).

To illustrate the functionality provided in this component, we begin by assuming that we have some user-defined type, MyType, comprising several data members:

struct MyType { // size 24; actual alignment 8; natural alignment 8
int d_int;
double d_double; // Assume 8-byte alignment.
char *d_charPtr; // Assume size <= 8 bytes.
};

We then define a function, f, which starts off by creating a maximally aligned buffer on the program stack:

void f()
{
// The remainder of the usage example is in the USAGE test case.
}
union {
bsls::AlignmentUtil::MaxAlignedType d_dummy; // force max. align.
char d_buffer[BUFFER_SIZE];
} buffer;
AlignmentToType< BSLS_MAX_ALIGNMENT >::Type MaxAlignedType
Definition bsls_alignmentutil.h:282

Next we use the bsls::AlignmentUtil functions directly to confirm that buffer is sufficiently aligned to accommodate a MaxAlignedType object:

int alignment = bsls::AlignmentFromType<
int offset =
buffer.d_buffer,
alignment);
assert(0 == offset); // sufficient alignment
Definition bsls_alignmentfromtype.h:376

Below we perform various memory allocations using our naturallyAlign helper function:

void *p = static_cast<void *>(buffer.d_buffer);
(void) naturallyAlign(&p, sizeof(char));
void *shortPtr5 = naturallyAlign(&p, 5 * sizeof(short));

Note that the address held in shortPtr is numerically divisible by the alignment of a short on the current platform:

assert(0 == ((static_cast<char *>(shortPtr5) - buffer.d_buffer) %
static bool is2ByteAligned(const void *address)
Definition bsls_alignmentutil.h:434

Next we use naturallyAlign to allocate a block of appropriate size and sufficient alignment to store a MyType object:

void *objPtr = naturallyAlign(&p, sizeof(MyType));

Note that the alignment of the address held in objPtr is numerically divisible by the actual alignment requirement:

Assuming buffer has sufficient capacity, and the alignments for char, short, and MyType are, respectively, 1, 2, and 8, we would expect this layout within buffer.d_buffer:

charPtr shortPtr5 objPtr
| | |
V V V
.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.-
|ccc| |sssssss:sssssss:sssssss:sssssss:sssssss| : : : |oooooo...
^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^-
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

Note that on an atypical 32-bit platform where a double is 4-byte aligned, the actual alignment of MyType would be 4, but its natural alignment would still be 8 because its size would be 16; it is highly unlikely that MyType would have an actual (and therefore natural) alignment of 4 on a 64-bit platform when using default compiler settings.

Typedef Documentation

◆ bsls_AlignmentUtil