Vc  1.1.0
SIMD Vector Classes for C++
Allocator
1 /* This file is part of the Vc library. {{{
2 Copyright © 2014 Matthias Kretz <kretz@kde.org>
3 All rights reserved.
4 
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.
15 
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.
26 
27 }}}*/
28 
29 #ifndef VC_ALLOCATOR_H_
30 #define VC_ALLOCATOR_H_
31 
32 #include <new>
33 #include <cstddef>
34 #include <cstdlib>
35 #include <utility>
36 
37 #include "global.h"
38 #include "common/macros.h"
39 
50 #ifdef Vc_MSVC
51 #define Vc_DECLARE_ALLOCATOR(Type) \
52 namespace std \
53 { \
54 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
55 { \
56 public: \
57  template <typename U> struct rebind { \
58  typedef ::std::allocator<U> other; \
59  }; \
60  /* MSVC brokenness: the following function is optional - just doesn't compile \
61  * without it */ \
62  const allocator &select_on_container_copy_construction() const { return *this; } \
63 }; \
64 }
65 #else
66 #define Vc_DECLARE_ALLOCATOR(Type) \
67 namespace std \
68 { \
69 template <> class allocator<Type> : public ::Vc::Allocator<Type> \
70 { \
71 public: \
72  template <typename U> struct rebind { \
73  typedef ::std::allocator<U> other; \
74  }; \
75 }; \
76 }
77 #endif
78 
79 namespace Vc_VERSIONED_NAMESPACE
80 {
81  using std::size_t;
82  using std::ptrdiff_t;
83 
129  template<typename T> class Allocator
130  {
131  private:
132  enum Constants {
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),
137 #else
138  NaturalAlignment = sizeof(void *) > alignof(long double) ? sizeof(void *) :
139  (alignof(long double) > alignof(long long) ? alignof(long double) : alignof(long long)),
140 #endif
141 #ifdef Vc_IMPL_MIC
142  SimdAlignment = 64,
143 #elif defined Vc_IMPL_AVX
144  SimdAlignment = 32,
145 #elif defined Vc_IMPL_SSE
146  SimdAlignment = 16,
147 #else
148  SimdAlignment = 1,
149 #endif
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.
154  *
155  * The address we get from ::operator new is a multiple of NaturalAlignment:
156  * p = N * NaturalAlignment
157  *
158  * Since all alignments are powers of two, Alignment is a multiple of NaturalAlignment:
159  * Alignment = k * NaturalAlignment
160  *
161  * two cases:
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.
166  */
167  ExtraBytes = Alignment > NaturalAlignment ? Alignment : 0,
168  AlignmentMask = Alignment - 1
169  };
170  public:
171  typedef size_t size_type;
172  typedef ptrdiff_t difference_type;
173  typedef T* pointer;
174  typedef const T* const_pointer;
175  typedef T& reference;
176  typedef const T& const_reference;
177  typedef T value_type;
178 
179  template<typename U> struct rebind { typedef Allocator<U> other; };
180 
181  Allocator() throw() { }
182  Allocator(const Allocator&) throw() { }
183  template<typename U> Allocator(const Allocator<U>&) throw() { }
184 
185  pointer address(reference x) const { return &x; }
186  const_pointer address(const_reference x) const { return &x; }
187 
188  pointer allocate(size_type n, const void* = 0)
189  {
190  if (n > this->max_size()) {
191  throw std::bad_alloc();
192  }
193 
194  char *p = static_cast<char *>(::operator new(n * sizeof(T) + ExtraBytes));
195  if (ExtraBytes > 0) {
196  char *const pp = p;
197  p += ExtraBytes;
198  const char *null = 0;
199  p -= ((p - null) & AlignmentMask); // equivalent to p &= ~AlignmentMask;
200  reinterpret_cast<char **>(p)[-1] = pp;
201  }
202  return reinterpret_cast<pointer>(p);
203  }
204 
205  void deallocate(pointer p, size_type)
206  {
207  if (ExtraBytes > 0) {
208  p = reinterpret_cast<pointer *>(p)[-1];
209  }
210  ::operator delete(p);
211  }
212 
213  size_type max_size() const throw() { return size_t(-1) / sizeof(T); }
214 
215 #ifdef Vc_MSVC
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; }
218 
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(); }
222 
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(); }
226 #else
227  template<typename U, typename... Args> void construct(U* p, Args&&... args)
228  {
229  ::new(p) U(std::forward<Args>(args)...);
230  }
231  template<typename U> void destroy(U* p) { p->~U(); }
232 #endif
233  };
234 
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; }
237 
238 }
239 
240 #include "vector.h"
241 namespace std
242 {
243  template<typename T> class allocator<Vc::Vector<T> > : public ::Vc::Allocator<Vc::Vector<T> >
244  {
245  public:
246  template<typename U> struct rebind { typedef ::std::allocator<U> other; };
247 #ifdef Vc_MSVC
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; }
250 #endif
251  };
252  template <typename T>
253  class allocator<Vc::Mask<T>> : public ::Vc::Allocator<Vc::Mask<T>>
254  {
255  public:
256  template<typename U> struct rebind { typedef ::std::allocator<U> other; };
257 #ifdef Vc_MSVC
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; }
260 #endif
261  };
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>>
264  {
265  public:
266  template<typename U> struct rebind { typedef ::std::allocator<U> other; };
267 #ifdef Vc_MSVC
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; }
270 #endif
271  };
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>>
274  {
275  public:
276  template<typename U> struct rebind { typedef ::std::allocator<U> other; };
277 #ifdef Vc_MSVC
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; }
280 #endif
281  };
282 }
283 
284 #endif // VC_ALLOCATOR_H_
285 
286 // vim: ft=cpp et sw=4 sts=4
The main vector class for expressing data parallelism.
Definition: types.h:45
Definition: vector.h:258
An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
Definition: Allocator:129
#define Vc_IMPL_AVX
This macro is defined if the current translation unit is compiled with AVX instruction support (exclu...
Definition: dox.h:612
#define Vc_IMPL_SSE
This macro is defined if the current translation unit is compiled with any version of SSE (but not AV...
Definition: dox.h:587
Vector Classes Namespace.
Definition: cpuid.h:33
#define Vc_IMPL_MIC
This macro is defined if the current translation unit is compiled for the Knights Corner Xeon Phi ins...
Definition: dox.h:621