1 /* This file is part of the Vc library. {{{
2 Copyright © 2014 Matthias Kretz <kretz@kde.org>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the names of contributing organizations nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifndef VC_ALLOCATOR_H_
30 #define VC_ALLOCATOR_H_
38 #include "common/macros.h"
43 * Convenience macro to set the default allocator for a given \p Type to
46 * \param Type Your type that you want to use with STL containers.
48 * \note You have to use this macro in the global namespace.
51 #define Vc_DECLARE_ALLOCATOR(Type) \
54 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
57 template <typename U> struct rebind { \
58 typedef ::std::allocator<U> other; \
60 /* MSVC brokenness: the following function is optional - just doesn't compile \
62 const allocator &select_on_container_copy_construction() const { return *this; } \
66 #define Vc_DECLARE_ALLOCATOR(Type) \
69 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
72 template <typename U> struct rebind { \
73 typedef ::std::allocator<U> other; \
79 namespace Vc_VERSIONED_NAMESPACE
85 * \headerfile Allocator <Vc/Allocator>
86 * An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
88 * Meant as a simple replacement for the allocator defined in the C++ Standard.
89 * Allocation is done using the global new/delete operators. But if the alignment property of \p
90 * T is larger than the size of a pointer, the allocate function allocates slightly more memory
91 * to adjust the pointer for correct alignment.
93 * If the \p T does not require over-alignment no additional memory will be allocated.
95 * \tparam T The type of objects to allocate.
100 * Vc::float_v x, y, z;
105 * std::vector<Data> dat0; // this will use std::allocator<Data>, which probably ignores the
106 * // alignment requirements for Data. Thus any access to dat0 may
107 * // crash your program.
109 * std::vector<Data, Vc::Allocator<Data> > dat1; // now std::vector will get correctly aligned
110 * // memory. Accesses to dat1 are safe.
114 * %Vc ships a macro to conveniently tell STL to use Vc::Allocator per default for a given type:
117 * Vc::float_v x, y, z;
119 * Vc_DECLARE_ALLOCATOR(Data)
123 * std::vector<Data> dat0; // good now
129 template<typename T> class Allocator
133 #ifdef Vc_HAVE_STD_MAX_ALIGN_T
134 NaturalAlignment = alignof(std::max_align_t),
135 #elif defined(Vc_HAVE_MAX_ALIGN_T)
136 NaturalAlignment = alignof(::max_align_t),
138 NaturalAlignment = sizeof(void *) > alignof(long double) ? sizeof(void *) :
139 (alignof(long double) > alignof(long long) ? alignof(long double) : alignof(long long)),
143 #elif defined Vc_IMPL_AVX
145 #elif defined Vc_IMPL_SSE
150 Alignment = alignof(T) > SimdAlignment ? alignof(T) : SimdAlignment,
151 /* The number of extra bytes allocated must be large enough to put a pointer right
152 * before the adjusted address. This pointer stores the original address, which is
153 * required to call ::operator delete in deallocate.
155 * The address we get from ::operator new is a multiple of NaturalAlignment:
156 * p = N * NaturalAlignment
158 * Since all alignments are powers of two, Alignment is a multiple of NaturalAlignment:
159 * Alignment = k * NaturalAlignment
162 * 1. If p is already aligned to Alignment then allocate will return p + Alignment. In
163 * this case there are Alignment Bytes available to store a pointer.
164 * 2. If p is not aligned then p + (k - (N modulo k)) * NaturalAlignment will be
165 * returned. Since NaturalAlignment >= sizeof(void*) the pointer fits.
167 ExtraBytes = Alignment > NaturalAlignment ? Alignment : 0,
168 AlignmentMask = Alignment - 1
171 typedef size_t size_type;
172 typedef ptrdiff_t difference_type;
174 typedef const T* const_pointer;
175 typedef T& reference;
176 typedef const T& const_reference;
177 typedef T value_type;
179 template<typename U> struct rebind { typedef Allocator<U> other; };
181 Allocator() throw() { }
182 Allocator(const Allocator&) throw() { }
183 template<typename U> Allocator(const Allocator<U>&) throw() { }
185 pointer address(reference x) const { return &x; }
186 const_pointer address(const_reference x) const { return &x; }
188 pointer allocate(size_type n, const void* = 0)
190 if (n > this->max_size()) {
191 throw std::bad_alloc();
194 char *p = static_cast<char *>(::operator new(n * sizeof(T) + ExtraBytes));
195 if (ExtraBytes > 0) {
198 const char *null = 0;
199 p -= ((p - null) & AlignmentMask); // equivalent to p &= ~AlignmentMask;
200 reinterpret_cast<char **>(p)[-1] = pp;
202 return reinterpret_cast<pointer>(p);
205 void deallocate(pointer p, size_type)
207 if (ExtraBytes > 0) {
208 p = reinterpret_cast<pointer *>(p)[-1];
210 ::operator delete(p);
213 size_type max_size() const throw() { return size_t(-1) / sizeof(T); }
216 // MSVC brokenness: the following function is optional - just doesn't compile without it
217 const Allocator &select_on_container_copy_construction() const { return *this; }
219 // MSVC also requires a function that neither C++98 nor C++11 mention
220 // but it doesn't support variadic templates... otherwise the Vc_CXX11 clause would be nice
221 void construct(pointer p) { ::new(p) T(); }
223 // we still need the C++98 version:
224 void construct(pointer p, const T& __val) { ::new(p) T(__val); }
225 void destroy(pointer p) { p->~T(); }
227 template<typename U, typename... Args> void construct(U* p, Args&&... args)
229 ::new(p) U(std::forward<Args>(args)...);
231 template<typename U> void destroy(U* p) { p->~U(); }
235 template<typename T> inline bool operator==(const Allocator<T>&, const Allocator<T>&) { return true; }
236 template<typename T> inline bool operator!=(const Allocator<T>&, const Allocator<T>&) { return false; }
243 template<typename T> class allocator<Vc::Vector<T> > : public ::Vc::Allocator<Vc::Vector<T> >
246 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
248 // MSVC brokenness: the following function is optional - just doesn't compile without it
249 const allocator &select_on_container_copy_construction() const { return *this; }
252 template <typename T>
253 class allocator<Vc::Mask<T>> : public ::Vc::Allocator<Vc::Mask<T>>
256 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
258 // MSVC brokenness: the following function is optional - just doesn't compile without it
259 const allocator &select_on_container_copy_construction() const { return *this; }
262 template <typename T, std::size_t N, typename V, std::size_t M>
263 class allocator<Vc::SimdArray<T, N, V, M>> : public ::Vc::Allocator<Vc::SimdArray<T, N, V, M>>
266 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
268 // MSVC brokenness: the following function is optional - just doesn't compile without it
269 const allocator &select_on_container_copy_construction() const { return *this; }
272 template <typename T, std::size_t N, typename V, std::size_t M>
273 class allocator<Vc::SimdMaskArray<T, N, V, M>> : public ::Vc::Allocator<Vc::SimdMaskArray<T, N, V, M>>
276 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
278 // MSVC brokenness: the following function is optional - just doesn't compile without it
279 const allocator &select_on_container_copy_construction() const { return *this; }
284 #endif // VC_ALLOCATOR_H_
286 // vim: ft=cpp et sw=4 sts=4