Ardour  9.0-pre0-582-g084a23a80d
stack_allocator.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef PBD_STACK_ALLOCATOR_H
20 #define PBD_STACK_ALLOCATOR_H
21 
22 #include <boost/type_traits/aligned_storage.hpp>
23 #include <limits>
24 
25 #include "pbd/libpbd_visibility.h"
26 
27 #if 0
28 # include <cstdio>
29 # define DEBUG_STACK_ALLOC(...) printf (__VA_ARGS__)
30 #else
31 # define DEBUG_STACK_ALLOC(...)
32 #endif
33 
34 namespace PBD {
35 
36 template <class T, std::size_t stack_capacity>
37 class /*LIBPBD_API*/ StackAllocator
38 {
39 public:
40 #if 0 /* may be needed for compatibility */
41  typedef typename std::allocator<T>::value_type value_type;
42  typedef typename std::allocator<T>::size_type size_type;
43  typedef typename std::allocator<T>::difference_type difference_type;
44  typedef typename std::allocator<T>::pointer pointer;
45  typedef typename std::allocator<T>::const_pointer const_pointer;
46  typedef typename std::allocator<T>::reference reference;
47  typedef typename std::allocator<T>::const_reference const_reference;
48 #else
49  typedef T value_type;
50  typedef std::size_t size_type;
51  typedef std::ptrdiff_t difference_type;
52  typedef value_type* pointer;
53  typedef const value_type* const_pointer;
55  typedef const value_type& const_reference;
56 #endif
57 
58  template <class U>
59  struct rebind {
61  };
62 
64  : _ptr ((pointer)&_buf)
65  { }
66 
68  : _ptr ((pointer)&_buf)
69  { }
70 
71  template <typename U, size_t other_capacity>
73  : _ptr ((pointer)&_buf)
74  { }
75 
76  /* inspired by http://howardhinnant.github.io/stack_alloc.h */
77  pointer allocate (size_type n, void* hint = 0)
78  {
79  if ((pointer)&_buf + stack_capacity >= _ptr + n) {
80  DEBUG_STACK_ALLOC ("Allocate %ld item(s) of size %zu on the stack\n", n, sizeof (T));
81  pointer rv = _ptr;
82  _ptr += n;
83  return rv;
84  } else {
85  DEBUG_STACK_ALLOC ("Allocate using new (%ld * %zu)\n", n, sizeof (T));
86  return static_cast<pointer> (::operator new (n * sizeof (T)));
87  }
88  }
89 
91  {
92  if (pointer_in_buffer (p)) {
93  if (p + n == _ptr) {
94  DEBUG_STACK_ALLOC ("Deallocate: pop item from the top of the stack\n");
95  _ptr = p;
96  } else {
97  DEBUG_STACK_ALLOC ("Deallocate: ignored. Item is not at the top of the stack \n");
98  }
99  } else {
100  ::operator delete (p);
101  }
102  }
103 
104  size_type max_size () const throw ()
105  {
106  return std::numeric_limits<size_type>::max () / sizeof (T);
107  }
108 
109  bool operator== (StackAllocator const& a) const
110  {
111  return &_buf == &a._buf;
112  }
113 
114  bool operator!= (StackAllocator const& a) const
115  {
116  return &_buf != &a._buf;
117  }
118 
119  template <class U>
120  void destroy (U* const p)
121  {
122  p->~U ();
123  }
124 
125  template <class U>
126  void construct (U* const p)
127  {
128  new (p) U ();
129  }
130 
131 #if __cplusplus > 201103L || defined __clang__
132  template <class U, class A>
133  void construct (U* const p, A* const a)
134  {
135  new (p) U (a);
136  }
137 #else
138  template <class U, class A>
139  void construct (U* const p, A const& a)
140  {
141  new (p) U (a);
142  }
143 #endif
144 
145 private:
147 
148  bool pointer_in_buffer (pointer const p)
149  {
150  return ((pointer const)&_buf <= p && p < (pointer const)&_buf + stack_capacity);
151  }
152 
153  typedef typename boost::aligned_storage<sizeof (T) * stack_capacity, 16>::type align_t;
154 
157 };
158 
159 } // namespace PBD
160 
161 #endif
void construct(U *const p)
boost::aligned_storage< sizeof(T) *stack_capacity, 16 >::type align_t
size_type max_size() const
pointer allocate(size_type n, void *hint=0)
StackAllocator & operator=(const StackAllocator &)
const value_type & const_reference
value_type * pointer
StackAllocator(const StackAllocator< U, other_capacity > &)
void construct(U *const p, A const &a)
bool pointer_in_buffer(pointer const p)
void destroy(U *const p)
std::ptrdiff_t difference_type
value_type & reference
void deallocate(pointer p, size_type n)
const value_type * const_pointer
bool operator!=(StackAllocator const &a) const
StackAllocator(const StackAllocator &)
bool operator==(StackAllocator const &a) const
Definition: axis_view.h:42
#define DEBUG_STACK_ALLOC(...)
StackAllocator< U, stack_capacity > other