From f9cffd69c526807a99f9f1d77ce37ef7915a885a Mon Sep 17 00:00:00 2001 From: NickStrupat Date: Sat, 10 May 2014 00:37:49 -0400 Subject: [PATCH] Settled on the guarantee that Aligned::Get() will return a reference to a T that will be alone on that aligned memory boundary. This is consistent with Aligned and it's variants. CacheAligned offers the same interfaces but with run-time determination of the cache line size. --- Aligned.hpp | 82 +++++++++++++++++++++++++++++++++--------------- CacheAligned.hpp | 22 +++---------- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/Aligned.hpp b/Aligned.hpp index 2e5c2be..9a35eae 100644 --- a/Aligned.hpp +++ b/Aligned.hpp @@ -6,64 +6,94 @@ #include #include "AlignedBase.hpp" -#define ALIGNED_BYTES_SIZE(T, sizeOfTPaddedToAlignment) sizeof(T) + sizeOfTPaddedToAlignment - 1 -#define ALIGNED_REF(T, bytes, sizeOfTPaddedToAlignment) *reinterpret_cast(uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) +#define ALIGNED_BYTES_SIZE(alignment, sizeOfTPaddedToAlignment) alignment + sizeOfTPaddedToAlignment - 1 +#define ALIGNED_POINTER(T, bytes, sizeOfTPaddedToAlignment) reinterpret_cast(uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) #define ALIGNED_ARRAY_BYTES_SIZE(T, sizeOfTPaddedToAlignment, size) sizeof(T) + (sizeOfTPaddedToAlignment * size) - 1 -#define ALIGNED_ARRAY_INDEX(T, bytes, sizeOfTPaddedToAlignment, index) *reinterpret_cast((uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) + (sizeOfTPaddedToAlignment * index)) +#define ALIGNED_ARRAY_INDEX_POINTER(T, bytes, sizeOfTPaddedToAlignment, index) reinterpret_cast((uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) + (sizeOfTPaddedToAlignment * index)) template class Aligned : AlignedBase { - uint8_t bytes[ALIGNED_BYTES_SIZE(T, SizeOfTPaddedToAlignment)]; + uint8_t bytes[ALIGNED_BYTES_SIZE(Alignment, SizeOfTPaddedToAlignment)]; + T * pValue; public: - Aligned() {} - Aligned(T const & value) { ref() = value; } - T & ref() { return ALIGNED_REF(T, bytes, SizeOfTPaddedToAlignment); } - T const & ref() const { return ref(); } + Aligned(T const & value = T()) + : pValue(ALIGNED_POINTER(T, bytes, SizeOfTPaddedToAlignment)) + { *pValue = T(value); } + ~Aligned() { pValue->~T(); } + T & Get() { return *pValue; } + T const & Get() const { return *pValue; } }; template class Aligned : AlignedBase { std::unique_ptr const pBytes; -protected: - Aligned(std::size_t alignment, void * ignoredParameterForOverload) : AlignedBase(alignment), pBytes(new uint8_t[alignment + sizeOfTPaddedToAlignment - 1]) {} + T * pValue; public: - Aligned(std::size_t alignment) : AlignedBase(alignment), pBytes(new uint8_t[ALIGNED_BYTES_SIZE(T, sizeOfTPaddedToAlignment)]) {} - Aligned(std::size_t alignment, T const & value) : Aligned(alignment) { ref() = value; } - T & ref() { return ALIGNED_REF(T, pBytes.get(), sizeOfTPaddedToAlignment); } - T const & ref() const { return ref(); } + Aligned(std::size_t alignment, T const & value = T()) + : AlignedBase(alignment), + pBytes(new uint8_t[ALIGNED_BYTES_SIZE(alignment, sizeOfTPaddedToAlignment)]), + pValue(ALIGNED_POINTER(T, pBytes.get(), sizeOfTPaddedToAlignment)) + { *pValue = T(value); } + ~Aligned() { pValue->~T(); } + T & Get() { return *pValue; } + T const & Get() const { return *pValue; } }; template -class Aligned : AlignedBase { +class Aligned : AlignedBase{ + static const std::size_t size = Size; uint8_t bytes[ALIGNED_ARRAY_BYTES_SIZE(T, SizeOfTPaddedToAlignment, Size)]; + T * pFirstElement; + T & element(std::size_t index) { return *reinterpret_cast(uintptr_t(pFirstElement) + (SizeOfTPaddedToAlignment * index)); } public: - Aligned() {} - T & operator[](std::size_t index) { return ALIGNED_ARRAY_INDEX(T, bytes, SizeOfTPaddedToAlignment, index); } - T const & operator[](std::size_t index) const { return operator[](index); } + Aligned() : pFirstElement(ALIGNED_POINTER(T, bytes, SizeOfTPaddedToAlignment)) {} + T & operator[](std::size_t index) { return element(index); } + T const & operator[](std::size_t index) const { return element(index); } + std::size_t Size() const { return size; } }; template class Aligned : AlignedBase { + std::size_t const size; std::unique_ptr const pBytes; + T * pFirstElement; + T & element(std::size_t index) { return *reinterpret_cast(uintptr_t(pFirstElement) + (SizeOfTPaddedToAlignment * index)); } public: - Aligned(std::size_t size) : pBytes(new uint8_t[ALIGNED_ARRAY_BYTES_SIZE(T, SizeOfTPaddedToAlignment, size)]) {} - T & operator[](std::size_t index) { return ALIGNED_ARRAY_INDEX(T, pBytes.get(), SizeOfTPaddedToAlignment, index); } - T const & operator[](std::size_t index) const { return operator[](index); } + Aligned(std::size_t size) + : size(size), + pBytes(new uint8_t[ALIGNED_ARRAY_BYTES_SIZE(T, SizeOfTPaddedToAlignment, size)]), + pFirstElement(ALIGNED_POINTER(T, pBytes.get(), SizeOfTPaddedToAlignment)) + { + std::cout << (int *)(pBytes.get()) << std::endl; + std::cout << pFirstElement << std::endl; + } + T & operator[](std::size_t index) { return element(index); } + T const & operator[](std::size_t index) const { return element(index); } + std::size_t Size() const { return size; } }; template class Aligned : AlignedBase { + std::size_t size; std::unique_ptr const pBytes; + T * pFirstElement; + T & element(std::size_t index) { return *reinterpret_cast(uintptr_t(pFirstElement) + (sizeOfTPaddedToAlignment * index)); } Aligned(); public: - Aligned(std::size_t alignment, std::size_t size) : AlignedBase(alignment), pBytes(new uint8_t[ALIGNED_ARRAY_BYTES_SIZE(T, sizeOfTPaddedToAlignment, size)]) {} - T & operator[](std::size_t index) { return ALIGNED_ARRAY_INDEX(T, pBytes.get(), sizeOfTPaddedToAlignment, index); } - T const & operator[](std::size_t index) const { return operator[](index); } + Aligned(std::size_t alignment, std::size_t size) + : AlignedBase(alignment), + size(size), + pBytes(new uint8_t[ALIGNED_ARRAY_BYTES_SIZE(T, sizeOfTPaddedToAlignment, size)]), + pFirstElement(ALIGNED_POINTER(T, pBytes.get(), sizeOfTPaddedToAlignment)) + {} + T & operator[](std::size_t index) { return element(index); } + T const & operator[](std::size_t index) const { return element(index); } + std::size_t Size() const { return size; } }; #undef ALIGNED_BYTES_SIZE -#undef ALIGNED_REF +#undef ALIGNED_POINTER #undef ALIGNED_ARRAY_BYTES_SIZE -#undef ALIGNED_ARRAY_INDEX +#undef ALIGNED_ARRAY_INDEX_POINTER #endif \ No newline at end of file diff --git a/CacheAligned.hpp b/CacheAligned.hpp index 9843d08..75be627 100644 --- a/CacheAligned.hpp +++ b/CacheAligned.hpp @@ -4,32 +4,18 @@ #include #include #include "CacheAlignedBase.hpp" -#include "Aligned.hpp" -#include "RoundUp.hpp" template -class CacheAligned : protected Aligned, CacheAlignedBase { +class CacheAligned : public Aligned, CacheAlignedBase { public: - CacheAligned() : Aligned(cacheLineSize(), nullptr) {} - CacheAligned(T const & value) : CacheAligned() { ref() = value; } - T & ref() { return *reinterpret_cast(&Aligned::ref()); } - T const & ref() const { return ref(); } -}; - -template -class CacheAligned : Aligned, CacheAlignedBase{ -public: - CacheAligned() : Aligned(cacheLineSize(), Size) {} - T & operator[](std::size_t index) { return *reinterpret_cast(&Aligned::operator[](index)); } - T const & operator[](std::size_t index) const { return operator[](index); } + CacheAligned() : Aligned(cacheLineSize()) {} + CacheAligned(T const & value) : Aligned(cacheLineSize(), value) {} }; template -class CacheAligned : Aligned, CacheAlignedBase { +class CacheAligned : public Aligned, CacheAlignedBase { public: CacheAligned(std::size_t size) : Aligned(cacheLineSize(), size) {} - T & operator[](std::size_t index) { return *reinterpret_cast(&Aligned::operator[](index)); } - T const & operator[](std::size_t index) const { return operator[](index); } }; #endif \ No newline at end of file