Skip to content

Commit

Permalink
Settled on the guarantee that Aligned<T>::Get() will return a referen…
Browse files Browse the repository at this point in the history
…ce to a T that will be alone on that aligned memory boundary. This is consistent with Aligned<T[]> and it's variants. CacheAligned<T> offers the same interfaces but with run-time determination of the cache line size.
  • Loading branch information
NickStrupat committed May 10, 2014
1 parent 6d430c3 commit f9cffd6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 44 deletions.
82 changes: 56 additions & 26 deletions Aligned.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,64 +6,94 @@
#include <memory>
#include "AlignedBase.hpp"

#define ALIGNED_BYTES_SIZE(T, sizeOfTPaddedToAlignment) sizeof(T) + sizeOfTPaddedToAlignment - 1
#define ALIGNED_REF(T, bytes, sizeOfTPaddedToAlignment) *reinterpret_cast<T *>(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<T *>(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<T *>((uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) + (sizeOfTPaddedToAlignment * index))
#define ALIGNED_ARRAY_INDEX_POINTER(T, bytes, sizeOfTPaddedToAlignment, index) reinterpret_cast<T *>((uintptr_t(bytes) + (sizeOfTPaddedToAlignment - 1) & ~uintptr_t(sizeOfTPaddedToAlignment - 1)) + (sizeOfTPaddedToAlignment * index))

template<typename T, std::size_t Alignment = -1>
class Aligned : AlignedBase<T, Alignment> {
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<typename T>
class Aligned<T, -1> : AlignedBase<T, -1> {
std::unique_ptr<uint8_t[]> 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<typename T, std::size_t Size, std::size_t Alignment>
class Aligned<T[Size], Alignment> : AlignedBase<T, Alignment> {
class Aligned<T[Size], Alignment> : AlignedBase<T, Alignment>{
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<T *>(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<typename T, std::size_t Alignment>
class Aligned<T[], Alignment> : AlignedBase<T, Alignment> {
std::size_t const size;
std::unique_ptr<uint8_t[]> const pBytes;
T * pFirstElement;
T & element(std::size_t index) { return *reinterpret_cast<T *>(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<typename T>
class Aligned<T[], -1> : AlignedBase<T, -1> {
std::size_t size;
std::unique_ptr<uint8_t[]> const pBytes;
T * pFirstElement;
T & element(std::size_t index) { return *reinterpret_cast<T *>(uintptr_t(pFirstElement) + (sizeOfTPaddedToAlignment * index)); }
Aligned();
public:
Aligned(std::size_t alignment, std::size_t size) : AlignedBase<T, -1>(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<T, -1>(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
22 changes: 4 additions & 18 deletions CacheAligned.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,18 @@
#include <cstddef>
#include <cstdint>
#include "CacheAlignedBase.hpp"
#include "Aligned.hpp"
#include "RoundUp.hpp"

template<typename T>
class CacheAligned : protected Aligned<T>, CacheAlignedBase {
class CacheAligned : public Aligned<T>, CacheAlignedBase {
public:
CacheAligned() : Aligned(cacheLineSize(), nullptr) {}
CacheAligned(T const & value) : CacheAligned() { ref() = value; }
T & ref() { return *reinterpret_cast<T *>(&Aligned::ref()); }
T const & ref() const { return ref(); }
};

template<typename T, std::size_t Size>
class CacheAligned<T[Size]> : Aligned<T[]>, CacheAlignedBase{
public:
CacheAligned() : Aligned(cacheLineSize(), Size) {}
T & operator[](std::size_t index) { return *reinterpret_cast<T *>(&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<typename T>
class CacheAligned<T[]> : Aligned<T[]>, CacheAlignedBase {
class CacheAligned<T[]> : public Aligned<T[]>, CacheAlignedBase {
public:
CacheAligned(std::size_t size) : Aligned(cacheLineSize(), size) {}
T & operator[](std::size_t index) { return *reinterpret_cast<T *>(&Aligned::operator[](index)); }
T const & operator[](std::size_t index) const { return operator[](index); }
};

#endif

0 comments on commit f9cffd6

Please sign in to comment.