Header file memory_manip.hpp
#define SIPLASPLAS_UTILITY_MEMORY_MANIP_HPP
#include <memory>
#include <cstdint>
#include <climits>
#include <siplasplas/utility/export.hpp>
namespace cpp
{
namespace detail
{
char* aligned_ptr(char* pointer, std::size_t alignment);
void* aligned_ptr(void* pointer, std::size_t alignment);
const char* aligned_ptr(const char* pointer, std::size_t alignment);
const void* aligned_ptr(const void* pointer, std::size_t alignment);
bool is_aligned(char* pointer, std::size_t alignment);
bool is_aligned(void* pointer, std::size_t alignment);
bool is_aligned(const char* pointer, std::size_t alignment);
bool is_aligned(const void* pointer, std::size_t alignment);
std::uintptr_t missalignment(const char* address, std::size_t alignment);
std::uintptr_t missalignment(const void* address, std::size_t alignment);
std::uintptr_t missalignment(char* address, std::size_t alignment);
std::uintptr_t missalignment(void* address, std::size_t alignment);
template <typename T, typename U>
T* tagPointer(T* pointer, U data);
template <typename R, typename U, typename ... Args>
decltype(pointer) tagPointer(R(*pointer)(Args...), U data);
template <typename T>
T* untagPointer(T* pointer);
template <typename R, typename ... Args>
decltype(pointer) untagPointer(R(*pointer)(Args...));
template <typename T>
std::uint16_t readTaggedPointer(T* pointer);
template <typename R, typename ... Args>
std::uint16_t readTaggedPointer(R(*pointer)(Args...));
using AlignedMallocAlingOffset = std::uint8_t;
void* aligned_malloc(std::size_t size, std::size_t alignment, std::size_t offset = 0);
void* aligned_malloc_block(void* pointer, std::size_t offset = 0);
void aligned_free(void* pointer, std::size_t offset = 0);
template <typename T>
void write_at(char* pointer, const T& value, std::intptr_t offset = 0);
template <typename T>
void write_at(void* pointer, const T& value, std::intptr_t offset = 0);
template <typename T>
T read_at(const char* pointer, std::intptr_t offset = 0);
template <typename T>
T read_at(const void* pointer, std::intptr_t offset = 0);
template <typename T>
void write_before(char* pointer, const T& value);
template <typename T>
void write_before(void* pointer, const T& value);
template <typename T>
T read_before(const char* pointer);
template <typename T>
T read_before(const void* pointer);
template <typename T>
class RawReaderWriter;
}
}
Function cpp::detail::aligned_ptr
char* aligned_ptr(char* pointer, std::size_t alignment);
Returns: The next (upper) address from the given address that’s aligned to the required boundary
Parameter cpp::detail::aligned_ptr::pointer
char* pointer
Starting address \param alignment Alignment boundary. Must be a power of two
Function cpp::detail::aligned_ptr
void* aligned_ptr(void* pointer, std::size_t alignment);
Returns: The next (upper) address from the given address that’s aligned to the required boundary
Parameter cpp::detail::aligned_ptr::pointer
void* pointer
Starting address \param alignment Alignment boundary. Must be a power of two
Function cpp::detail::aligned_ptr
const char* aligned_ptr(const char* pointer, std::size_t alignment);
Returns: The next (upper) address from the given address that’s aligned to the required boundary
Parameter cpp::detail::aligned_ptr::pointer
const char* pointer
Starting address \param alignment Alignment boundary. Must be a power of two
Function cpp::detail::aligned_ptr
const void* aligned_ptr(const void* pointer, std::size_t alignment);
Returns: The next (upper) address from the given address that’s aligned to the required boundary
Parameter cpp::detail::aligned_ptr::pointer
const void* pointer
Starting address \param alignment Alignment boundary. Must be a power of two
Function cpp::detail::is_aligned
bool is_aligned(char* pointer, std::size_t alignment);
Returns: true if \p pointer is aligned to \p alignment boundary. False otherwise.
Parameter cpp::detail::is_aligned::pointer
char* pointer
Address to check \param alignment Required alignment. Must be a power of two
Function cpp::detail::is_aligned
bool is_aligned(void* pointer, std::size_t alignment);
Returns: true if \p pointer is aligned to \p alignment boundary. False otherwise.
Parameter cpp::detail::is_aligned::pointer
void* pointer
Address to check \param alignment Required alignment. Must be a power of two
Function cpp::detail::is_aligned
bool is_aligned(const char* pointer, std::size_t alignment);
Returns: true if \p pointer is aligned to \p alignment boundary. False otherwise.
Parameter cpp::detail::is_aligned::pointer
const char* pointer
Address to check \param alignment Required alignment. Must be a power of two
Function cpp::detail::is_aligned
bool is_aligned(const void* pointer, std::size_t alignment);
Returns: true if \p pointer is aligned to \p alignment boundary. False otherwise.
Parameter cpp::detail::is_aligned::pointer
const void* pointer
Address to check \param alignment Required alignment. Must be a power of two
Function cpp::detail::missalignment
std::uintptr_t missalignment(const char* address, std::size_t alignment);
Returns: The distance in bytes to the next aligned address
Parameter cpp::detail::missalignment::address
const char* address
Memory address \param alignment Required alignment. Must be a power of two
Function cpp::detail::missalignment
std::uintptr_t missalignment(const void* address, std::size_t alignment);
Returns: The distance in bytes to the next aligned address
Parameter cpp::detail::missalignment::address
const void* address
Memory address \param alignment Required alignment. Must be a power of two
Function cpp::detail::missalignment
std::uintptr_t missalignment(char* address, std::size_t alignment);
Returns: The distance in bytes to the next aligned address
Parameter cpp::detail::missalignment::address
char* address
Memory address \param alignment Required alignment. Must be a power of two
Function cpp::detail::missalignment
std::uintptr_t missalignment(void* address, std::size_t alignment);
Returns: The distance in bytes to the next aligned address
Parameter cpp::detail::missalignment::address
void* address
Memory address \param alignment Required alignment. Must be a power of two
Function template cpp::detail::tagPointer<T, U>
template <typename T, typename U>
T* tagPointer(T* pointer, U data);
This function uses the tagged pointer technique to store data in a 64 bit virtual memory address. Passing data of more than 16 bits wide has undefined behavior. Compilation fails if this function is used in non 64 bit architectures. Note accessing a tagged pointer directly may cause a segmentation fault. See cpp::untagPointer().
Returns: A pointer of type T* with the data and the same address
Template parameter cpp::detail::tagPointer<T, U>::T
typename T
Pointed type \tparam U Must be an integral type of max sizeof(U) = 16 bit \param pointer pointer where to store data \param data data to store
Function template cpp::detail::tagPointer<R, U, Args...>
template <typename R, typename U, typename ... Args>
decltype(pointer) tagPointer(R(*pointer)(Args...), U data);
This function uses the tagged pointer technique to store data in a 64 bit virtual memory address. Passing data of more than 16 bits wide has undefined behavior. Compilation fails if this function is used in non 64 bit architectures. Note accessing a tagged pointer directly may cause a segmentation fault. See cpp::untagPointer().
Returns: A pointer of type T* with the data and the same address
Template parameter cpp::detail::tagPointer<R, U, Args...>::U
typename U
Must be an integral type of max sizeof(U) = 16 bit \param pointer pointer where to store data \param data data to store
Function template cpp::detail::untagPointer<T>
template <typename T>
T* untagPointer(T* pointer);
Assuming the pointer is a tagged pointer, this function removes the tagged data and returns the memory address ready to be referenced. Compilation fails if this function is used in non 64 bit architectures.
Returns: The given pointer with the 16 upper bits cleared
Parameter cpp::detail::untagPointer::pointer
T* pointer
Tagged pointer to clear
Function template cpp::detail::untagPointer<R, Args...>
template <typename R, typename ... Args>
decltype(pointer) untagPointer(R(*pointer)(Args...));
Assuming the pointer is a tagged pointer, this function removes the tagged data and returns the memory address ready to be referenced. Compilation fails if this function is used in non 64 bit architectures.
Returns: The given pointer with the 16 upper bits cleared
Parameter cpp::detail::untagPointer::pointer
R(*pointer)(Args...)
Tagged pointer to clear
Function template cpp::detail::readTaggedPointer<T>
template <typename T>
std::uint16_t readTaggedPointer(T* pointer);
Assuming the pointer is a tagged pointer, this function reads the data tagged in the 16 more significative bits of the pointer. Compilation fails if this function is used in non 64 bit architectures.
Returns: The 16 bit unsigned integer value tagged in the pointer
Parameter cpp::detail::readTaggedPointer::pointer
T* pointer
Tagged pointer to read
Function template cpp::detail::readTaggedPointer<R, Args...>
template <typename R, typename ... Args>
std::uint16_t readTaggedPointer(R(*pointer)(Args...));
Assuming the pointer is a tagged pointer, this function reads the data tagged in the 16 more significative bits of the pointer. Compilation fails if this function is used in non 64 bit architectures.
Returns: The 16 bit unsigned integer value tagged in the pointer
Parameter cpp::detail::readTaggedPointer::pointer
R(*pointer)(Args...)
Tagged pointer to read
Type alias cpp::detail::AlignedMallocAlingOffset
using AlignedMallocAlingOffset = std::uint8_t;
This type limits the maximum alignment requirement that can be passed to aligned_malloc() stores the distance to the start of the allocated block so it can be deallocated in aligned_free(). To use as little extra memory as possible, a 8 bit unsigned integer is used by default, which means up to 256 byte alignment boundary is supported by default. Users can change that limit by defining SIPLASPLAS_UTILITY_ALIGNEDMALLOC_ALIGNOFFSET_BITS
to the with in bits of the unsigned integer used for offset storage (8, 16, 32, and 64 are supported)
#define SIPLASPLAS_UTILITY_ALIGNEDMALLOC_ALIGNEDOFFSET_BITS 32
#include <siplasplas/utility/memory_manip.hpp>
void* ptr =cpp::aligned_malloc(1024, 1024); // Allocate 1024 bytes in the 1024 boundary
Function cpp::detail::aligned_malloc
void* aligned_malloc(std::size_t size, std::size_t alignment, std::size_t offset = 0);
This function allocates a memory block starting at a specific alignment boundary. Users can also set some extra bytes for bookeeping data before the returned block. To deallocate blocks allocated with aligned_malloc(), use aligned_free(), never std::free()
Returns: A pointer to a memory block of \p size bytes, multiple of \p alignment. nullptr if fails
Parameter cpp::detail::aligned_malloc::size
std::size_t size
Requested block size in bytes \param alignment Required alignment boundary. Must be a power of two \param offset Extra space reserved for the user right brefore the returned block. 0 by default.
Function cpp::detail::aligned_malloc_block
void* aligned_malloc_block(void* pointer, std::size_t offset = 0);
aligned_malloc() allocates an oversized block in order to acomplish the alignment requirements While aligned_malloc() returns the expected aligned block, this function can be used to get the complete allocated block.
Returns: A pointer to the beginning of the complete allocated block. This pointer can be deallocated by std::free()
.
Parameter cpp::detail::aligned_malloc_block::pointer
void* pointer
Pointer to a block allocated by cpp::aligned_malloc() \param offset User offset. The behavior is undefined if it’s different to the argument given to cpp::aligned_malloc() when allocating the block