1 /* Copyright (C) 2010 Wildfire Games. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining 4 * a copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sublicense, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 /* 24 * STL allocator for aligned memory 25 */ 26 27 #ifndef ALIGNED_ALLOCATOR 28 #define ALIGNED_ALLOCATOR 29 30 #include "lib/bits.h" // round_up 31 #include "lib/sysdep/arch/x86_x64/cache.h" 32 #include "lib/sysdep/rtl.h" // rtl_AllocateAligned 33 34 35 /** 36 * stateless STL allocator that aligns elements to the L1 cache line size. 37 * 38 * note: the alignment is hard-coded to avoid any allocator state. 39 * this avoids portability problems, which is important since allocators 40 * are rather poorly specified. 41 * 42 * references: 43 * http://www.tantalon.com/pete/customallocators.ppt 44 * http://www.flipcode.com/archives/Aligned_Block_Allocation.shtml 45 * http://www.josuttis.com/cppcode/allocator.html 46 * 47 * derived from code that bears the following copyright notice: 48 * (C) Copyright Nicolai M. Josuttis 1999. 49 * Permission to copy, use, modify, sell and distribute this software 50 * is granted provided this copyright notice appears in all copies. 51 * This software is provided "as is" without express or implied 52 * warranty, and with no claim as to its suitability for any purpose. 53 **/ 54 template<class T> 55 class AlignedAllocator 56 { 57 public: 58 // type definitions 59 typedef T value_type; 60 typedef T* pointer; 61 typedef const T* const_pointer; 62 typedef T& reference; 63 typedef const T& const_reference; 64 typedef std::size_t size_type; 65 typedef std::ptrdiff_t difference_type; 66 67 // rebind allocator to type U 68 template <class U> 69 struct rebind 70 { 71 typedef AlignedAllocator<U> other; 72 }; 73 address(reference value)74 pointer address(reference value) const 75 { 76 return &value; 77 } 78 address(const_reference value)79 const_pointer address(const_reference value) const 80 { 81 return &value; 82 } 83 AlignedAllocator()84 NOTHROW_DEFINE AlignedAllocator() 85 { 86 } 87 AlignedAllocator(const AlignedAllocator &)88 NOTHROW_DEFINE AlignedAllocator(const AlignedAllocator&) 89 { 90 } 91 92 template <class U> AlignedAllocator(const AlignedAllocator<U> &)93 NOTHROW_DEFINE AlignedAllocator (const AlignedAllocator<U>&) 94 { 95 } 96 ~AlignedAllocator()97 NOTHROW_DEFINE ~AlignedAllocator() 98 { 99 } 100 max_size()101 NOTHROW_DEFINE size_type max_size() const 102 { 103 // maximum number of *elements* that can be allocated 104 return std::numeric_limits<std::size_t>::max() / sizeof(T); 105 } 106 107 // allocate uninitialized storage allocate(size_type numElements)108 pointer allocate(size_type numElements) 109 { 110 const size_type alignment = x86_x64::Caches(x86_x64::L1D)->entrySize; 111 const size_type elementSize = round_up(sizeof(T), alignment); 112 const size_type size = numElements * elementSize; 113 pointer p = (pointer)rtl_AllocateAligned(size, alignment); 114 return p; 115 } 116 117 // deallocate storage of elements that have been destroyed deallocate(pointer p,size_type UNUSED (num))118 void deallocate(pointer p, size_type UNUSED(num)) 119 { 120 rtl_FreeAligned((void*)p); 121 } 122 construct(pointer p,const T & value)123 void construct(pointer p, const T& value) 124 { 125 new((void*)p) T(value); 126 } 127 destroy(pointer p)128 void destroy(pointer p) 129 { 130 p->~T(); 131 UNUSED2(p); // otherwise, warning is raised for reasons unknown 132 } 133 }; 134 135 // indicate that all specializations of this allocator are interchangeable 136 template <class T1, class T2> 137 NOTHROW_DEFINE bool operator==(const AlignedAllocator<T1>&, const AlignedAllocator<T2>&) 138 { 139 return true; 140 } 141 142 template <class T1, class T2> 143 NOTHROW_DEFINE bool operator!=(const AlignedAllocator<T1>&, const AlignedAllocator<T2>&) 144 { 145 return false; 146 } 147 148 #endif // #ifndef ALIGNED_ALLOCATOR 149