Lumiera  0.pre.03
»edit your freedom«
simple-allocator.hpp
Go to the documentation of this file.
1 /*
2  SIMPLE-ALLOCATOR.hpp - frontend for plain explicit allocations
3 
4  Copyright (C) Lumiera.org
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
46 #ifndef LIB_SIMPLE_ALLOCATOR_H
47 #define LIB_SIMPLE_ALLOCATOR_H
48 
49 #include "lib/error.hpp"
50 #include "lib/meta/generator.hpp"
52 #include "lib/meta/util.hpp"
53 #include "lib/typed-counter.hpp"
54 #include "include/logging.h"
55 
56 #include <boost/static_assert.hpp>
57 #include <memory>
58 
59 
60 
61 namespace lib {
62 
63  using lib::meta::Types;
64  using lib::meta::IsInList;
66 
67 
68 
69  /* === Policies for simple custom allocator === */
70 
77  template<typename TY>
79  : public std::allocator<TY>
80  { };
81 
82 
88  {
89  template<class XX>
90  size_t
91  allocationCount() const
92  {
93  return allocCnt_.get<XX>();
94  }
95 
96  template<class XX>
97  void
98  incrementCount()
99  {
100  allocCnt_.inc<XX>();
101  }
102 
103  template<class XX>
104  void
105  decrementCount()
106  {
107  allocCnt_.dec<XX>();
108  }
109 
110  private:
111  lib::TypedCounter allocCnt_;
112  };
113 
118  {
119  template<class XX> size_t allocationCount() const { return 0; }
120  template<class XX> void incrementCount() { /* NOP */ }
121  template<class XX> void decrementCount() { /* NOP */ }
122  };
123 
124 
125 
126 
127 
128 
129  /* === Allocator frontend === */
130 
142  template<typename TYPES
143  ,class COUNTER = NoInstantiationCount
144  >
146  : InstantiateForEach< typename TYPES::List // for each of those types...
147  , CustomAllocator // ...mix in the custom allocator
148  >
149  , COUNTER // ...Instantiation accounting policy
150  {
151 
153  template<class XX>
154  XX *
156  {
157  TRACE (memory, "allocate «%s»", util::typeStr<XX>().c_str());
158  XX * newStorage = CustomAllocator<XX>::allocate (1);
159  COUNTER::template incrementCount<XX>();
160  return newStorage;
161  }
162 
163  template<class XX>
164  void
165  releaseSlot (XX* entry)
166  {
167  TRACE (memory, "release «%s»", util::typeStr<XX>().c_str());
169  COUNTER::template decrementCount<XX>();
170  }
171 
172 
173  template<class XX>
174  void
175  ___assertSupportedType()
176  {
177  typedef typename TYPES::List PreconfiguredTypes;
178  typedef IsInList<XX, PreconfiguredTypes> IsSupportedType;
179 
180  BOOST_STATIC_ASSERT (IsSupportedType::value);
181  }
182 
183 
184 
185 
186  public: /* ==== build objects with managed allocation ==== */
187 
188 #define _EXCEPTION_SAFE_INVOKE(_CTOR_) \
189  \
190  ___assertSupportedType<XX>(); \
191  XX* storage = allocateSlot<XX>(); \
192  try \
193  { \
194  return (new(storage) _CTOR_ ); \
195  } \
196  catch(...) \
197  { \
198  releaseSlot<XX>(storage); \
199  throw; \
200  }
201 
202  template< class XX>
203  XX* //_____________________
204  create ()
205  {
206  _EXCEPTION_SAFE_INVOKE ( XX() )
207  }
208 
209 
210  template< class XX, typename P1>
211  XX* //___________________
212  create (P1& p1)
213  {
214  _EXCEPTION_SAFE_INVOKE ( XX (p1) )
215  }
216 
217 
218  template< class XX
219  , typename P1
220  , typename P2
221  >
222  XX* //___________________
223  create (P1& p1, P2& p2)
224  {
225  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2) )
226  }
227 
228 
229  template< class XX
230  , typename P1
231  , typename P2
232  , typename P3
233  >
234  XX* //___________________
235  create (P1& p1, P2& p2, P3& p3)
236  {
237  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3) )
238  }
239 
240 
241  template< class XX
242  , typename P1
243  , typename P2
244  , typename P3
245  , typename P4
246  >
247  XX* //___________________
248  create (P1& p1, P2& p2, P3& p3, P4& p4)
249  {
250  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4) )
251  }
252 
253 
254  template< class XX
255  , typename P1
256  , typename P2
257  , typename P3
258  , typename P4
259  , typename P5
260  >
261  XX* //___________________
262  create (P1& p1, P2& p2, P3& p3, P4& p4, P5& p5)
263  {
264  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4,p5) )
265  }
266 
267 #undef _EXCEPTION_SAFE_INVOKE
268 
269 
270 
271  template<class XX>
272  void
273  destroy (XX* entry)
274  {
275  if (!entry) return;
276  ___assertSupportedType<XX>();
277  try
278  {
279  entry->~XX();
280  }
281  catch(...)
282  {
283  lumiera_err errorID = lumiera_error();
284  WARN (common_dbg, "dtor of «%s» failed: %s", util::typeStr(entry).c_str()
285  , errorID );
286  }
287  releaseSlot<XX> (entry);
288  }
289 
290 
292  template<class XX>
293  size_t
294  numSlots() const
295  {
296  return COUNTER::template allocationCount<XX>();
297  }
298  };
299 
300 
301 
302 
303 } // namespace lib
304 #endif
Policy: no additional instantiation accounting.
Creating series of type-based contexts.
Utility providing a set of counters, each tied to a specific type.
size_t numSlots() const
diagnostics
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
XX * create(P1 &p1, P2 &p2)
Simple and lightweight helpers for metaprogramming and type detection.
Metafunction to check if a specific type is contained in a given typelist.
Apply a template to a collection of types.
Definition: generator.hpp:80
Helpers for working with lib::meta::Types (i.e.
Metaprogramming: simple helpers for working with lists-of-types.
This header is for including and configuring NoBug.
Implementation namespace for support and library code.
XX * create(P1 &p1, P2 &p2, P3 &p3, P4 &p4)
lumiera_err lumiera_error(void)
Get and clear current error state.
Definition: error-state.c:124
Frontend for explicit allocations, using a custom allocator.
XX * create(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5)
Lumiera error handling (C++ interface).
XX * allocateSlot()
forward plain memory allocation
XX * create(P1 &p1, P2 &p2, P3 &p3)
Policy: use just plain heap allocations whenever you define a specialisation, you are responsible fo...
Policy: maintain explicit per type instance count.