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

Macros

#define bsls_AlignmentOf   bsls::AlignmentFromType
 

Typedefs

typedef bsls::Alignment bsls_Alignment
 This alias is defined for backward compatibility.
 

Detailed Description

Outline

Purpose

Provide a namespace for enumerating memory alignment strategies.

Classes

See also
bsls_alignmentutil

Description

This component provides a namespace, bsls::Alignment, for enumerating alignment strategies, and provides a function, toAscii, that converts each of the enumerators to its corresponding string representation.

Alignment Strategy

This component supports three alignment strategies: 1) MAXIMUM ALIGNMENT, 2) NATURAL ALIGNMENT, and 3) 1-BYTE ALIGNMENT.

  1. MAXIMUM ALIGNMENT: This strategy, as indicated by the enumerator BSLS_MAXIMUM, specifies that a memory block be aligned as per the most restrictive alignment requirement on the host platform.
  2. NATURAL ALIGNMENT: This strategy, as indicated by the enumerator BSLS_NATURAL, specifies that a memory block be aligned based on the size (in bytes) of that block. An object of a fundamental type (int, etc.) is naturally aligned when its size evenly divides its address. An object of an aggregate type has natural alignment if the alignment of the most-restrictively aligned sub-object evenly divides the address of the aggregate. Natural alignment is always at least as restrictive as the compiler's required alignment.
  3. 1-BYTE ALIGNMENT: This strategy, as indicated by the enumerator BSLS_BYTEALIGNED, specifies that a memory block may be aligned arbitrarily on any 1-byte boundary. This is the least restrictive alignment requirement.

Usage

Suppose that we want to create a static function, allocateFromBuffer, that takes a buffer, the size of the buffer, a cursor indicating a position within the buffer, an allocation request size, and a memory alignment strategy; allocateFromBuffer returns a pointer to a block of memory, wholly contained within the buffer, having the specified size and alignment. As a side-effect, the cursor is updated to refer to the next available free byte in the buffer. Such a function could be used by a memory manager to satisfy allocation requests from internally-managed buffers. Clients of this function indicate which alignment strategy to use based on their specific requirements.

Our allocateFromBuffer function depends on an alignment utility, my_AlignmentUtil, whose minimal interface is limited to that required by this usage example. (See the bsls_alignmentutil component for a more realistic alignment utility.):

struct my_AlignmentUtil {
// This 'struct' provides a namespace for basic types and utilities
// related to memory alignment.
// TYPES
/// Provide the *minimal* value that satisfies the alignment
/// requirements for *all* types on the host platform. Note that 8
/// is used for illustration purposes only; an actual implementation
/// would employ template meta-programming to deduce the value at
/// compile time.
enum {
MY_MAX_PLATFORM_ALIGNMENT = 8
};
// CLASS METHODS
/// Calculate a usable alignment for a memory block of the specified
/// `size` (in bytes) in the absence of compile-time knowledge of
/// the block's alignment requirements. Return the largest power of
/// two that evenly divides `size`, up to a maximum of
/// `MY_MAX_PLATFORM_ALIGNMENT`. It is guaranteed that a block of
/// `size` bytes can be safely aligned on the return value. The
/// behavior is undefined unless `0 < size`.
static int calculateAlignmentFromSize(int size);
/// Return the smallest non-negative offset (in bytes) that, when
/// added to the specified `address`, yields the specified
/// `alignment`. The behavior is undefined unless `0 != alignment`
/// and `alignment` is a non-negative, integral power of 2.
static int calculateAlignmentOffset(const void *address,
int alignment);
};

The definition of our allocateFromBuffer function is as follows:

/// Allocate a memory block of the specified `size` (in bytes) from the
/// specified `buffer` having the specified `bufferSize` at the
/// specified `cursor` position, using the specified alignment
/// `strategy`. Return the address of the allocated memory block if
/// `buffer` contains sufficient available memory, and 0 otherwise. The
/// `cursor` is set to the first byte position immediately after the
/// allocated memory (which might be 1 byte past the end of `buffer`) if
/// there is sufficient memory, and is not modified otherwise. The
/// behavior is undefined unless `0 <= bufferSize`, `0 < size`, and
/// `cursor` refers to a valid position in `buffer`.
static void *allocateFromBuffer(int *cursor,
char *buffer,
int bufferSize,
int size,
{
Strategy
Types of alignment strategy.
Definition bsls_alignment.h:239

First we assert the function pre-conditions:

assert(cursor);
assert(buffer);
assert(0 <= bufferSize);
assert(0 < size);

Then, based on the alignment strategy, we calculate the alignment value that can satisfy the allocation request. In the case of bsls::Alignment::BSLS_NATURAL, we calculate the alignment from size; for bsls::Alignment::BSLS_MAXIMUM, we use the platform-dependent my_AlignmentUtil::MY_MAX_PLATFORM_ALIGNMENT value; and for bsls::Alignment::BSLS_BYTEALIGNED, we simply use 1:

const int alignment =
? my_AlignmentUtil::calculateAlignmentFromSize(size)
: strategy == bsls::Alignment::BSLS_MAXIMUM
? my_AlignmentUtil::MY_MAX_PLATFORM_ALIGNMENT
: 1;
Definition bdlt_iso8601util.h:691
@ BSLS_NATURAL
Definition bsls_alignment.h:246

Now we calculate the offset from the current cursor value that can satisfy the alignment requirements:

const int offset = my_AlignmentUtil::calculateAlignmentOffset(
buffer + *cursor,
alignment);

Next we check if the available free memory in buffer can satisfy the allocation request; 0 is returned if the request cannot be satisfied:

if (*cursor + offset + size > bufferSize) {
return 0; // RETURN
}
void *result = &buffer[*cursor + offset];
*cursor += offset + size;

Finally, return the address of the correctly aligned memory block:

return result;
}

The allocateFromBuffer function may be used by a memory manager that needs to appropriately align memory blocks that are allocated from internally-managed buffers. For an example, see the bslma_bufferimputil component.

Macro Definition Documentation

◆ bsls_AlignmentOf

#define bsls_AlignmentOf   bsls::AlignmentFromType

Typedef Documentation

◆ bsls_Alignment