Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
AlignedAllocator.hpp
1 #pragma once
2 #include <Core/RaCore.hpp>
3 
4 #ifdef _WIN32
5 # include <malloc.h>
6 #elif !defined ARCH_ARM32 && !defined ARCH_ARM64 || defined _WIN32
7 # include <mm_malloc.h>
8 #endif
9 #include <cstddef>
10 #include <cstdint>
11 #include <cstdlib>
12 
13 namespace Ra {
14 namespace Core {
23 template <typename T, std::size_t Alignment>
25 {
26  public:
27  // The following will be the same for virtually all allocators.
28  using pointer = T*;
29  using const_pointer = const T*;
30  using reference = T&;
31  using const_reference = const T&;
32  using value_type = T;
33  using size_type = std::size_t;
34  using difference_type = ptrdiff_t;
35 
36  T* address( T& r ) const { return &r; }
37 
38  const T* address( const T& s ) const { return &s; }
39 
40  std::size_t max_size() const {
41  // The following has been carefully written to be independent of
42  // the definition of size_t and to avoid signed/unsigned warnings.
43  return ( static_cast<std::size_t>( 0 ) - static_cast<std::size_t>( 1 ) ) / sizeof( T );
44  }
45 
46  // The following must be the same for all allocators.
47  template <typename U>
48  struct rebind {
49  using other = AlignedAllocator<U, Alignment>;
50  };
51 
52  bool operator!=( const AlignedAllocator& other ) const { return !( *this == other ); }
53 
54  void construct( T* const p, const T& t ) const {
55  void* const pv = static_cast<void*>( p );
56  new ( pv ) T( t );
57  }
58 
59  void destroy( T* const p ) const { p->~T(); }
60 
61  // Returns true if and only if storage allocated from *this
62  // can be deallocated from other, and vice versa.
63  // Always returns true for stateless allocators.
64  bool operator==( const AlignedAllocator& /*other*/ ) const { return true; }
65 
66  // Default constructor, copy constructor, rebinding constructor, and destructor.
67  // Empty for stateless allocators.
68  AlignedAllocator() {}
69 
71 
72  template <typename U>
74 
75  ~AlignedAllocator() {}
76 
77  // The following will be different for each allocator.
78  T* allocate( const std::size_t n ) const {
79  // The return value of allocate(0) is unspecified.
80  // Mallocator returns NULL in order to avoid depending
81  // on malloc(0)'s implementation-defined behavior
82  // (the implementation can define malloc(0) to return NULL,
83  // in which case the bad_alloc check below would fire).
84  // All allocators can return NULL in this case.
85  if ( n == 0 ) { return NULL; }
86 
87  // All allocators should contain an integer overflow check.
88  // The Standardization Committee recommends that std::length_error
89  // be thrown in the case of integer overflow.
90  CORE_ASSERT( n <= max_size(), "Integer overflow" );
91 
92 #if !defined ARCH_ARM32 && !defined ARCH_ARM64 || defined _WIN32
93  void* const pv = _mm_malloc( n * sizeof( T ), Alignment );
94 #else
95  void* const pv = aligned_alloc( Alignment, n * sizeof( T ) );
96 #endif
97 
98  // Allocators should throw std::bad_alloc in the case of memory allocation failure.
99  CORE_ASSERT( pv != NULL, " Bad alloc" );
100  CORE_ASSERT( ( reinterpret_cast<std::size_t>( pv ) & ( Alignment - 1 ) ) == 0,
101  "Alignment constraint not satisfied" );
102 
103  return static_cast<T*>( pv );
104  }
105 
106  void deallocate( T* const p, const std::size_t /*n*/ ) const {
107 #if !defined ARCH_ARM32 && !defined ARCH_ARM64 || defined _WIN32
108  _mm_free( p );
109 #else
110  free( p );
111 #endif
112  }
113 
114  // The following will be the same for all allocators that ignore hints.
115  template <typename U>
116  T* allocate( const std::size_t n, const U* /* const hint */ ) const {
117  return allocate( n );
118  }
119 
120  // Allocators are not required to be assignable, so
121  // all allocators should have a private unimplemented
122  // assignment operator. Note that this will trigger the
123  // off-by-default (enabled under /Wall) warning C4626
124  // "assignment operator could not be generated because a
125  // base class assignment operator is inaccessible" within
126  // the STL headers, but that warning is useless.
127  private:
128  AlignedAllocator& operator=( const AlignedAllocator& ) = delete;
129 };
130 
131 } // namespace Core
132 } // namespace Ra
Definition: Cage.cpp:3