1 /* This file is part of the Vc library. {{{
3 Copyright (C) 2012 Matthias Kretz <kretz@kde.org>
5 Vc is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation, either version 3 of
8 the License, or (at your option) any later version.
10 Vc is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with Vc. If not, see <http://www.gnu.org/licenses/>.
20 #ifndef VC_ALLOCATOR_H
21 #define VC_ALLOCATOR_H
26 #include "common/macros.h"
38 * \headerfile Allocator <Vc/Allocator>
41 * Convenience macro to set the default allocator for a given \p Type to Vc::Allocator.
43 * \param Type Your type that you want to use with STL containers.
45 * \note You have to use this macro in the global namespace.
47 #define VC_DECLARE_ALLOCATOR(Type) \
50 template<> class allocator<Type> : public ::AliRoot::Vc::Allocator<Type> \
53 template<typename U> struct rebind { typedef ::std::allocator<U> other; }; \
57 #undef Vc_DECLARE_ALLOCATOR
58 #define Vc_DECLARE_ALLOCATOR(Type) \
61 template<> class allocator<Type> : public ::AliRoot::Vc::Allocator<Type> \
64 template<typename U> struct rebind { typedef ::std::allocator<U> other; }; \
65 /* MSVC brokenness: the following function is optional - just doesn't compile without it */ \
66 const allocator &select_on_container_copy_construction() const { return *this; } \
72 * \headerfile Allocator <Vc/Allocator>
73 * An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
75 * Meant as a simple replacement for the allocator defined in the C++ Standard.
76 * Allocation is done using the global new/delete operators. But if the alignment property of \p
77 * T is larger than the size of a pointer, the allocate function allocates slightly more memory
78 * to adjust the pointer for correct alignment.
80 * If the \p T does not require over-alignment no additional memory will be allocated.
82 * \tparam T The type of objects to allocate.
87 * Vc::float_v x, y, z;
92 * std::vector<Data> dat0; // this will use std::allocator<Data>, which probably ignores the
93 * // alignment requirements for Data. Thus any access to dat0 may
94 * // crash your program.
96 * std::vector<Data, Vc::Allocator<Data> > dat1; // now std::vector will get correctly aligned
97 * // memory. Accesses to dat1 are safe.
101 * %Vc ships a macro to conveniently tell STL to use Vc::Allocator per default for a given type:
104 * Vc::float_v x, y, z;
106 * VC_DECLARE_ALLOCATOR(Data)
110 * std::vector<Data> dat0; // good now
116 template<typename T> class Allocator
120 #ifdef VC_HAVE_STD_MAX_ALIGN_T
121 NaturalAlignment = alignof(std::max_align_t),
122 #elif defined(VC_HAVE_MAX_ALIGN_T)
123 NaturalAlignment = alignof(::max_align_t),
125 NaturalAlignment = sizeof(void *) > Vc_ALIGNOF(long double) ? sizeof(void *) :
126 (Vc_ALIGNOF(long double) > Vc_ALIGNOF(long long) ? Vc_ALIGNOF(long double) : Vc_ALIGNOF(long long)),
128 Alignment = Vc_ALIGNOF(T),
129 /* The number of extra bytes allocated must be large enough to put a pointer right
130 * before the adjusted address. This pointer stores the original address, which is
131 * required to call ::operator delete in deallocate.
133 * The address we get from ::operator new is a multiple of NaturalAlignment:
134 * p = N * NaturalAlignment
136 * Since all alignments are powers of two, Alignment is a multiple of NaturalAlignment:
137 * Alignment = k * NaturalAlignment
140 * 1. If p is already aligned to Alignment then allocate will return p + Alignment. In
141 * this case there are Alignment Bytes available to store a pointer.
142 * 2. If p is not aligned then p + (k - (N modulo k)) * NaturalAlignment will be
143 * returned. Since NaturalAlignment >= sizeof(void*) the pointer fits.
145 ExtraBytes = Alignment > NaturalAlignment ? Alignment : 0,
146 AlignmentMask = Alignment - 1
149 typedef size_t size_type;
150 typedef ptrdiff_t difference_type;
152 typedef const T* const_pointer;
153 typedef T& reference;
154 typedef const T& const_reference;
155 typedef T value_type;
157 template<typename U> struct rebind { typedef Allocator<U> other; };
159 Allocator() throw() { }
160 Allocator(const Allocator&) throw() { }
161 template<typename U> Allocator(const Allocator<U>&) throw() { }
163 pointer address(reference x) const { return &x; }
164 const_pointer address(const_reference x) const { return &x; }
166 pointer allocate(size_type n, const void* = 0)
168 if (n > this->max_size()) {
169 throw std::bad_alloc();
172 char *p = static_cast<char *>(::operator new(n * sizeof(T) + ExtraBytes));
173 if (ExtraBytes > 0) {
176 const char *null = 0;
177 p -= ((p - null) & AlignmentMask); // equivalent to p &= ~AlignmentMask;
178 reinterpret_cast<char **>(p)[-1] = pp;
180 return reinterpret_cast<pointer>(p);
183 void deallocate(pointer p, size_type)
185 if (ExtraBytes > 0) {
186 p = reinterpret_cast<pointer *>(p)[-1];
188 ::operator delete(p);
191 size_type max_size() const throw() { return size_t(-1) / sizeof(T); }
194 // MSVC brokenness: the following function is optional - just doesn't compile without it
195 const Allocator &select_on_container_copy_construction() const { return *this; }
197 // MSVC also requires a function that neither C++98 nor C++11 mention
198 // but it doesn't support variadic templates... otherwise the VC_CXX11 clause would be nice
199 void construct(pointer p) { ::new(p) T(); }
201 // we still need the C++98 version:
202 void construct(pointer p, const T& __val) { ::new(p) T(__val); }
203 void destroy(pointer p) { p->~T(); }
204 #elif defined(VC_CXX11)
205 template<typename U, typename... Args> void construct(U* p, Args&&... args)
207 ::new(p) U(std::forward<Args>(args)...);
209 template<typename U> void destroy(U* p) { p->~U(); }
211 void construct(pointer p, const T& __val) { ::new(p) T(__val); }
212 void destroy(pointer p) { p->~T(); }
216 template<typename T> inline bool operator==(const Allocator<T>&, const Allocator<T>&) { return true; }
217 template<typename T> inline bool operator!=(const Allocator<T>&, const Allocator<T>&) { return false; }
220 } // namespace AliRoot
222 #include "common/undomacros.h"
226 template<typename T> class allocator<Vc::Vector<T> > : public ::AliRoot::Vc::Allocator<Vc::Vector<T> >
229 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
231 // MSVC brokenness: the following function is optional - just doesn't compile without it
232 const allocator &select_on_container_copy_construction() const { return *this; }
237 #endif // VC_ALLOCATOR_H
239 // vim: ft=cpp et sw=4 sts=4