Added uninitialized_buffer

This commit is contained in:
John Wellbelove 2020-10-19 08:40:51 +01:00
parent 89adab63d9
commit c31e5c83e7
2 changed files with 196 additions and 0 deletions

View File

@ -37,6 +37,7 @@ SOFTWARE.
#include "iterator.h"
#include "utility.h"
#include "nullptr.h"
#include "alignment.h"
#include <assert.h>
@ -1900,6 +1901,156 @@ namespace etl
memory_clear(static_cast<volatile T&>(*this));
}
};
//***************************************************************************
/// Declares an aligned buffer of N_OBJECTS x of size OBJECT_SIZE at alignment ALIGNMENT.
///\ingroup alignment
//***************************************************************************
template <size_t OBJECT_SIZE_, size_t N_OBJECTS_, size_t ALIGNMENT_>
class uninitialized_buffer
{
public:
static ETL_CONSTANT size_t OBJECT_SIZE = OBJECT_SIZE_;
static ETL_CONSTANT size_t N_OBJECTS = N_OBJECTS_;
static ETL_CONSTANT size_t ALIGNMENT = ALIGNMENT_;
/// Convert to T reference.
template <typename T>
operator T& ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return *reinterpret_cast<T*>(raw);
}
/// Convert to const T reference.
template <typename T>
operator const T& () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return *reinterpret_cast<const T*>(raw);
}
/// Convert to T pointer.
template <typename T>
operator T* ()
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<T*>(raw);
}
/// Convert to const T pointer.
template <typename T>
operator const T* () const
{
ETL_STATIC_ASSERT((etl::is_same<T*, void*>::value || ((ALIGNMENT % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
return reinterpret_cast<const T*>(raw);
}
#if ETL_CPP11_SUPPORTED && !defined(ETL_COMPILER_ARM5) && !defined(ETL_UNINITIALIZED_BUFFER_FORCE_CPP03)
alignas(ALIGNMENT) char raw[OBJECT_SIZE * N_OBJECTS];
#else
union
{
char raw[OBJECT_SIZE * N_OBJECTS];
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT.
};
#endif
};
//***************************************************************************
/// Declares an aligned buffer of N_OBJECTS as if they were type T.
///\ingroup alignment
//***************************************************************************
template <typename T, size_t N_OBJECTS_>
class uninitialized_buffer_of
{
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
typedef T* iterator;
typedef const T* const_iterator;
static ETL_CONSTANT size_t OBJECT_SIZE = sizeof(T);
static ETL_CONSTANT size_t N_OBJECTS = N_OBJECTS_;
static ETL_CONSTANT size_t ALIGNMENT = etl::alignment_of<T>::value;
/// Index operator.
T& operator [](int i)
{
return ((T*)this->raw)[i];
}
/// Index operator.
const T& operator [](int i) const
{
return ((T*)this->raw)[i];
}
/// Convert to T reference.
operator T& ()
{
return *reinterpret_cast<T*>(raw);
}
/// Convert to const T reference.
operator const T& () const
{
return *reinterpret_cast<const T*>(raw);
}
/// Convert to T pointer.
operator T* ()
{
return reinterpret_cast<T*>(raw);
}
/// Convert to const T pointer.
operator const T* () const
{
return reinterpret_cast<const T*>(raw);
}
T* begin()
{
return reinterpret_cast<const T*>(raw);
}
const T* begin() const
{
return reinterpret_cast<const T*>(raw);
}
T* end()
{
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_OBJECTS));
}
const T* end() const
{
return reinterpret_cast<const T*>(raw + (sizeof(T) * N_OBJECTS));
}
#if ETL_CPP11_SUPPORTED && !defined(ETL_COMPILER_ARM5) && !defined(ETL_UNINITIALIZED_BUFFER_FORCE_CPP03)
alignas(ALIGNMENT) char raw[sizeof(T) * N_OBJECTS];
#else
union
{
char raw[sizeof(T) * N_OBJECTS];
typename etl::type_with_alignment<ALIGNMENT>::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT.
};
#endif
};
#if ETL_CPP14_SUPPORTED
template <typename T, size_t N_OBJECTS>
using uninitialized_buffer_of_v = typename uninitialized_buffer_of<T, N_OBJECTS>::buffer;
#endif
}
#endif

View File

@ -1040,5 +1040,50 @@ namespace
CHECK_EQUAL(6, up1[2]);
CHECK_EQUAL(7, up1[3]);
}
//*************************************************************************
TEST(test_uninitialized_buffer)
{
typedef etl::uninitialized_buffer<sizeof(uint32_t), 4, etl::alignment_of_v<uint32_t>> storage32_t;
size_t alignment = etl::alignment_of_v<storage32_t>;
size_t expected = std::alignment_of_v<uint32_t>;
CHECK_EQUAL(expected, alignment);
}
//*************************************************************************
TEST(test_uninitialized_buffer_of)
{
typedef etl::uninitialized_buffer_of<uint32_t, 4> storage32_t;
static storage32_t buffer;
uint32_t* i = buffer;
const uint32_t* ci = buffer;
CHECK(i == ci);
buffer[0] = 0U;
buffer[1] = 1U;
buffer[2] = 2U;
buffer[3] = 3U;
CHECK_EQUAL(0U, buffer[0]);
CHECK_EQUAL(1U, buffer[1]);
CHECK_EQUAL(2U, buffer[2]);
CHECK_EQUAL(3U, buffer[3]);
const storage32_t& refbuffer = buffer;
CHECK_EQUAL(0U, refbuffer[0]);
CHECK_EQUAL(1U, refbuffer[1]);
CHECK_EQUAL(2U, refbuffer[2]);
CHECK_EQUAL(3U, refbuffer[3]);
size_t alignment = etl::alignment_of_v<storage32_t>;
size_t expected = std::alignment_of_v<uint32_t>;
CHECK_EQUAL(expected, alignment);
}
};
}