Warning, /include/Vc/Allocator is written in an unsupported language. File is not indexed.
0001 /* This file is part of the Vc library. {{{
0002 Copyright © 2014 Matthias Kretz <kretz@kde.org>
0003
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006 * Redistributions of source code must retain the above copyright
0007 notice, this list of conditions and the following disclaimer.
0008 * Redistributions in binary form must reproduce the above copyright
0009 notice, this list of conditions and the following disclaimer in the
0010 documentation and/or other materials provided with the distribution.
0011 * Neither the names of contributing organizations nor the
0012 names of its contributors may be used to endorse or promote products
0013 derived from this software without specific prior written permission.
0014
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025
0026 }}}*/
0027
0028 #ifndef VC_ALLOCATOR_H_
0029 #define VC_ALLOCATOR_H_
0030
0031 #include <new>
0032 #include <cstddef>
0033 #include <cstdlib>
0034 #include <utility>
0035
0036 #include "global.h"
0037 #include "common/macros.h"
0038
0039 /**
0040 * \ingroup Utilities
0041 *
0042 * Convenience macro to set the default allocator for a given \p Type to
0043 * Vc::Allocator.
0044 *
0045 * \param Type Your type that you want to use with STL containers.
0046 *
0047 * \note You have to use this macro in the global namespace.
0048 */
0049 #ifdef Vc_MSVC
0050 #define Vc_DECLARE_ALLOCATOR(Type) \
0051 namespace std \
0052 { \
0053 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
0054 { \
0055 public: \
0056 template <typename U> struct rebind { \
0057 typedef ::std::allocator<U> other; \
0058 }; \
0059 /* MSVC brokenness: the following function is optional - just doesn't compile \
0060 * without it */ \
0061 const allocator &select_on_container_copy_construction() const { return *this; } \
0062 }; \
0063 }
0064 #else
0065 #define Vc_DECLARE_ALLOCATOR(Type) \
0066 namespace std \
0067 { \
0068 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
0069 { \
0070 public: \
0071 template <typename U> struct rebind { \
0072 typedef ::std::allocator<U> other; \
0073 }; \
0074 }; \
0075 }
0076 #endif
0077
0078 namespace Vc_VERSIONED_NAMESPACE
0079 {
0080 using std::size_t;
0081 using std::ptrdiff_t;
0082
0083 /**
0084 * \headerfile Allocator <Vc/Allocator>
0085 * An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
0086 *
0087 * Meant as a simple replacement for the allocator defined in the C++ Standard.
0088 * Allocation is done using the global new/delete operators. But if the alignment property of \p
0089 * T is larger than the size of a pointer, the allocate function allocates slightly more memory
0090 * to adjust the pointer for correct alignment.
0091 *
0092 * If the \p T does not require over-alignment no additional memory will be allocated.
0093 *
0094 * \tparam T The type of objects to allocate.
0095 *
0096 * Example:
0097 * \code
0098 * struct Data {
0099 * Vc::float_v x, y, z;
0100 * };
0101 *
0102 * void fun()
0103 * {
0104 * std::vector<Data> dat0; // this will use std::allocator<Data>, which probably ignores the
0105 * // alignment requirements for Data. Thus any access to dat0 may
0106 * // crash your program.
0107 *
0108 * std::vector<Data, Vc::Allocator<Data> > dat1; // now std::vector will get correctly aligned
0109 * // memory. Accesses to dat1 are safe.
0110 * ...
0111 * \endcode
0112 *
0113 * %Vc ships a macro to conveniently tell STL to use Vc::Allocator per default for a given type:
0114 * \code
0115 * struct Data {
0116 * Vc::float_v x, y, z;
0117 * };
0118 * Vc_DECLARE_ALLOCATOR(Data)
0119 *
0120 * void fun()
0121 * {
0122 * std::vector<Data> dat0; // good now
0123 * ...
0124 * \endcode
0125 *
0126 * \ingroup Utilities
0127 */
0128 template<typename T> class Allocator
0129 {
0130 private:
0131 enum Constants {
0132 #ifdef Vc_HAVE_STD_MAX_ALIGN_T
0133 NaturalAlignment = alignof(std::max_align_t),
0134 #elif defined(Vc_HAVE_MAX_ALIGN_T)
0135 NaturalAlignment = alignof(::max_align_t),
0136 #else
0137 NaturalAlignment = sizeof(void *) > alignof(long double) ? sizeof(void *) :
0138 (alignof(long double) > alignof(long long) ? alignof(long double) : alignof(long long)),
0139 #endif
0140 #if defined Vc_IMPL_AVX
0141 SimdAlignment = 32,
0142 #elif defined Vc_IMPL_SSE
0143 SimdAlignment = 16,
0144 #else
0145 SimdAlignment = 1,
0146 #endif
0147 Alignment = alignof(T) > SimdAlignment ? alignof(T) : SimdAlignment,
0148 /* The number of extra bytes allocated must be large enough to put a pointer right
0149 * before the adjusted address. This pointer stores the original address, which is
0150 * required to call ::operator delete in deallocate.
0151 *
0152 * The address we get from ::operator new is a multiple of NaturalAlignment:
0153 * p = N * NaturalAlignment
0154 *
0155 * Since all alignments are powers of two, Alignment is a multiple of NaturalAlignment:
0156 * Alignment = k * NaturalAlignment
0157 *
0158 * two cases:
0159 * 1. If p is already aligned to Alignment then allocate will return p + Alignment. In
0160 * this case there are Alignment Bytes available to store a pointer.
0161 * 2. If p is not aligned then p + (k - (N modulo k)) * NaturalAlignment will be
0162 * returned. Since NaturalAlignment >= sizeof(void*) the pointer fits.
0163 */
0164 ExtraBytes = Alignment > NaturalAlignment ? Alignment : 0,
0165 AlignmentMask = Alignment - 1
0166 };
0167 public:
0168 typedef size_t size_type;
0169 typedef ptrdiff_t difference_type;
0170 typedef T* pointer;
0171 typedef const T* const_pointer;
0172 typedef T& reference;
0173 typedef const T& const_reference;
0174 typedef T value_type;
0175
0176 template<typename U> struct rebind { typedef Allocator<U> other; };
0177
0178 Allocator() throw() { }
0179 Allocator(const Allocator&) throw() { }
0180 template<typename U> Allocator(const Allocator<U>&) throw() { }
0181
0182 pointer address(reference x) const { return &x; }
0183 const_pointer address(const_reference x) const { return &x; }
0184
0185 pointer allocate(size_type n, const void* = 0)
0186 {
0187 if (n > this->max_size()) {
0188 throw std::bad_alloc();
0189 }
0190
0191 char *p = static_cast<char *>(::operator new(n * sizeof(T) + ExtraBytes));
0192 if (ExtraBytes > 0) {
0193 char *const pp = p;
0194 p += ExtraBytes;
0195 const char *null = 0;
0196 p -= ((p - null) & AlignmentMask); // equivalent to p &= ~AlignmentMask;
0197 reinterpret_cast<char **>(p)[-1] = pp;
0198 }
0199 return reinterpret_cast<pointer>(p);
0200 }
0201
0202 void deallocate(pointer p, size_type)
0203 {
0204 if (ExtraBytes > 0) {
0205 p = reinterpret_cast<pointer *>(p)[-1];
0206 }
0207 ::operator delete(p);
0208 }
0209
0210 size_type max_size() const throw() { return size_t(-1) / sizeof(T); }
0211
0212 #ifdef Vc_MSVC
0213 // MSVC brokenness: the following function is optional - just doesn't compile without it
0214 const Allocator &select_on_container_copy_construction() const { return *this; }
0215
0216 // MSVC also requires a function that neither C++98 nor C++11 mention
0217 // but it doesn't support variadic templates... otherwise the Vc_CXX11 clause would be nice
0218 void construct(pointer p) { ::new(p) T(); }
0219
0220 // we still need the C++98 version:
0221 void construct(pointer p, const T& val) { ::new(p) T(val); }
0222 void destroy(pointer p) { p->~T(); }
0223 #else
0224 template<typename U, typename... Args> void construct(U* p, Args&&... args)
0225 {
0226 ::new(p) U(std::forward<Args>(args)...);
0227 }
0228 template<typename U> void destroy(U* p) { p->~U(); }
0229 #endif
0230 };
0231
0232 template<typename T> inline bool operator==(const Allocator<T>&, const Allocator<T>&) { return true; }
0233 template<typename T> inline bool operator!=(const Allocator<T>&, const Allocator<T>&) { return false; }
0234
0235 }
0236
0237 #include "vector.h"
0238 namespace std
0239 {
0240 template<typename T, typename Abi>
0241 class allocator<Vc::Vector<T, Abi> > : public ::Vc::Allocator<Vc::Vector<T, Abi> >
0242 {
0243 public:
0244 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
0245 #ifdef Vc_MSVC
0246 // MSVC brokenness: the following function is optional - just doesn't compile without it
0247 const allocator &select_on_container_copy_construction() const { return *this; }
0248 #endif
0249 };
0250 template <typename T, typename Abi>
0251 class allocator<Vc::Mask<T, Abi>> : public ::Vc::Allocator<Vc::Mask<T, Abi>>
0252 {
0253 public:
0254 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
0255 #ifdef Vc_MSVC
0256 // MSVC brokenness: the following function is optional - just doesn't compile without it
0257 const allocator &select_on_container_copy_construction() const { return *this; }
0258 #endif
0259 };
0260 template <typename T, std::size_t N, typename V, std::size_t M>
0261 class allocator<Vc::SimdArray<T, N, V, M>> : public ::Vc::Allocator<Vc::SimdArray<T, N, V, M>>
0262 {
0263 public:
0264 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
0265 #ifdef Vc_MSVC
0266 // MSVC brokenness: the following function is optional - just doesn't compile without it
0267 const allocator &select_on_container_copy_construction() const { return *this; }
0268 #endif
0269 };
0270 template <typename T, std::size_t N, typename V, std::size_t M>
0271 class allocator<Vc::SimdMaskArray<T, N, V, M>> : public ::Vc::Allocator<Vc::SimdMaskArray<T, N, V, M>>
0272 {
0273 public:
0274 template<typename U> struct rebind { typedef ::std::allocator<U> other; };
0275 #ifdef Vc_MSVC
0276 // MSVC brokenness: the following function is optional - just doesn't compile without it
0277 const allocator &select_on_container_copy_construction() const { return *this; }
0278 #endif
0279 };
0280 }
0281
0282 #endif // VC_ALLOCATOR_H_
0283
0284 // vim: ft=cpp et sw=4 sts=4