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