openMSX
AlignedBuffer.hh
Go to the documentation of this file.
1 #ifndef ALIGNEDBUFFER_HH
2 #define ALIGNEDBUFFER_HH
3 
4 #include "alignof.hh"
5 #include <type_traits>
6 #include <cassert>
7 #include <cstdint>
8 #include <cstddef>
9 
10 namespace openmsx {
11 
12 // Hack for visual studio, remove when we can use c++11 alignas/alignof
13 #ifdef _MSC_VER
14  #ifdef _WIN64
15  #define MAX_ALIGN_V 16
16  #else
17  #define MAX_ALIGN_V 8
18  #endif
19 #else
20  // This only works starting from gcc-4-9
21  // #define MAX_ALIGN_V ALIGNOF(MAX_ALIGN_T)
22  #ifdef __x86_64
23  #define MAX_ALIGN_V 16
24  #else
25  #define MAX_ALIGN_V 8
26  #endif
27 #endif
28 
29 // Interface for an aligned buffer.
30 // This type doesn't itself provide any storage, it only 'refers' to some
31 // storage. In that sense it is very similar in usage to a 'uint8_t*'.
32 //
33 // For example:
34 // void f1(uint8_t* buf) {
35 // ... uint8_t x = buf[7];
36 // ... buf[4] = 10;
37 // ... uint8_t* begin = buf;
38 // ... uint8_t* end = buf + 12;
39 // }
40 // void f2(AlignedBuffer& buf) {
41 // // The exact same syntax as above, the only difference is that here
42 // // the compiler knows at compile-time the alignment of 'buf', while
43 // // above the compiler must assume worst case alignment.
44 // }
45 #ifdef _MSC_VER
46 // TODO in the future use the c++11 'alignas' feature
47 __declspec (align(MAX_ALIGN_V))
48 #endif
50 {
51 public:
52  static const size_t ALIGNMENT = MAX_ALIGN_V;
53 
54  operator uint8_t*() { return p(); }
55  operator const uint8_t*() const { return p(); }
56 
57  uint8_t* operator+(ptrdiff_t i) { return p() + i; };
58  const uint8_t* operator+(ptrdiff_t i) const { return p() + i; };
59 
60  uint8_t& operator[](int i) { return *(p() + i); }
61  const uint8_t& operator[](int i) const { return *(p() + i); }
62  uint8_t& operator[](unsigned int i) { return *(p() + i); }
63  const uint8_t& operator[](unsigned int i) const { return *(p() + i); }
64  uint8_t& operator[](long i) { return *(p() + i); }
65  const uint8_t& operator[](long i) const { return *(p() + i); }
66  uint8_t& operator[](unsigned long i) { return *(p() + i); }
67  const uint8_t& operator[](unsigned long i) const { return *(p() + i); }
68 
69 private:
70  uint8_t* p() { return reinterpret_cast< uint8_t*>(this); }
71  const uint8_t* p() const { return reinterpret_cast<const uint8_t*>(this); }
72 }
73 #ifndef _MSC_VER
74 __attribute__((__aligned__((MAX_ALIGN_V))))
75 #endif
76 ;
77 static_assert(ALIGNOF(AlignedBuffer) == AlignedBuffer::ALIGNMENT, "must be aligned");
78 
79 
80 // Provide actual storage for the AlignedBuffer
81 // A possible alternative is to use a union.
82 template<size_t N> class AlignedByteArray : public AlignedBuffer
83 {
84 public:
85  size_t size() const { return N; }
86  uint8_t* data() { return dat; }
87  const uint8_t* data() const { return dat; }
88 
89 private:
90  uint8_t dat[N];
91 
92 }
93 // Repeat alignment because Clang 3.2svn does not inherit it from an empty
94 // base class.
95 #ifndef _MSC_VER
96 __attribute__((__aligned__((MAX_ALIGN_V))))
97 #endif
98 ;
99 static_assert(ALIGNOF(AlignedByteArray<13>) == AlignedBuffer::ALIGNMENT,
100  "must be aligned");
101 static_assert(sizeof(AlignedByteArray<32>) == 32,
102  "we rely on the empty-base optimization");
103 
104 
109 template<typename T> static inline T aligned_cast(void* p)
110 {
111  static_assert(std::is_pointer<T>::value,
112  "can only perform aligned_cast on pointers");
113  assert((reinterpret_cast<uintptr_t>(p) %
114  ALIGNOF(typename std::remove_pointer<T>::type)) == 0);
115  return reinterpret_cast<T>(p);
116 }
117 
118 } //namespace openmsx
119 
120 #endif
const uint8_t * data() const
const uint8_t & operator[](int i) const
const uint8_t & operator[](long i) const
uint8_t & operator[](long i)
uint8_t & operator[](int i)
uint8_t & operator[](unsigned int i)
#define MAX_ALIGN_V
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
const uint8_t & operator[](unsigned long i) const
static const size_t ALIGNMENT
const uint8_t * operator+(ptrdiff_t i) const
uint8_t * operator+(ptrdiff_t i)
uint8_t * data()
class openmsx::AlignedBuffer __aligned__((MAX_ALIGN_V))))
uint8_t & operator[](unsigned long i)
const uint8_t & operator[](unsigned int i) const
#define ALIGNOF(T)
Definition: alignof.hh:25