Back to home page

EIC code displayed by LXR

 
 

    


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