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