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)
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
37 #ifndef LIB_SIMPLE_ALLOCATOR_H
38 #define LIB_SIMPLE_ALLOCATOR_H
39 
40 #include "lib/error.hpp"
41 #include "lib/meta/generator.hpp"
43 #include "lib/meta/util.hpp"
44 #include "lib/typed-counter.hpp"
45 #include "include/logging.h"
46 
47 #include <boost/static_assert.hpp>
48 #include <memory>
49 
50 
51 
52 namespace lib {
53 
54  using lib::meta::Types;
55  using lib::meta::IsInList;
57 
58 
59 
60  /* === Policies for simple custom allocator === */
61 
68  template<typename TY>
70  : public std::allocator<TY>
71  { };
72 
73 
79  {
80  template<class XX>
81  size_t
82  allocationCount() const
83  {
84  return allocCnt_.get<XX>();
85  }
86 
87  template<class XX>
88  void
89  incrementCount()
90  {
91  allocCnt_.inc<XX>();
92  }
93 
94  template<class XX>
95  void
96  decrementCount()
97  {
98  allocCnt_.dec<XX>();
99  }
100 
101  private:
102  lib::TypedCounter allocCnt_;
103  };
104 
109  {
110  template<class XX> size_t allocationCount() const { return 0; }
111  template<class XX> void incrementCount() { /* NOP */ }
112  template<class XX> void decrementCount() { /* NOP */ }
113  };
114 
115 
116 
117 
118 
119 
120  /* === Allocator frontend === */
121 
133  template<typename TYPES
134  ,class COUNTER = NoInstantiationCount
135  >
137  : InstantiateForEach< typename TYPES::List // for each of those types...
138  , CustomAllocator // ...mix in the custom allocator
139  >
140  , COUNTER // ...Instantiation accounting policy
141  {
142 
144  template<class XX>
145  XX *
147  {
148  TRACE (memory, "allocate «%s»", util::typeStr<XX>().c_str());
149  XX * newStorage = CustomAllocator<XX>::allocate (1);
150  COUNTER::template incrementCount<XX>();
151  return newStorage;
152  }
153 
154  template<class XX>
155  void
156  releaseSlot (XX* entry)
157  {
158  TRACE (memory, "release «%s»", util::typeStr<XX>().c_str());
160  COUNTER::template decrementCount<XX>();
161  }
162 
163 
164  template<class XX>
165  void
166  ___assertSupportedType()
167  {
168  typedef typename TYPES::List PreconfiguredTypes;
169  typedef IsInList<XX, PreconfiguredTypes> IsSupportedType;
170 
171  BOOST_STATIC_ASSERT (IsSupportedType::value);
172  }
173 
174 
175 
176 
177  public: /* ==== build objects with managed allocation ==== */
178 
179 #define _EXCEPTION_SAFE_INVOKE(_CTOR_) \
180  \
181  ___assertSupportedType<XX>(); \
182  XX* storage = allocateSlot<XX>(); \
183  try \
184  { \
185  return (new(storage) _CTOR_ ); \
186  } \
187  catch(...) \
188  { \
189  releaseSlot<XX>(storage); \
190  throw; \
191  }
192 
193  template< class XX>
194  XX* //_____________________
195  create ()
196  {
197  _EXCEPTION_SAFE_INVOKE ( XX() )
198  }
199 
200 
201  template< class XX, typename P1>
202  XX* //___________________
203  create (P1& p1)
204  {
205  _EXCEPTION_SAFE_INVOKE ( XX (p1) )
206  }
207 
208 
209  template< class XX
210  , typename P1
211  , typename P2
212  >
213  XX* //___________________
214  create (P1& p1, P2& p2)
215  {
216  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2) )
217  }
218 
219 
220  template< class XX
221  , typename P1
222  , typename P2
223  , typename P3
224  >
225  XX* //___________________
226  create (P1& p1, P2& p2, P3& p3)
227  {
228  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3) )
229  }
230 
231 
232  template< class XX
233  , typename P1
234  , typename P2
235  , typename P3
236  , typename P4
237  >
238  XX* //___________________
239  create (P1& p1, P2& p2, P3& p3, P4& p4)
240  {
241  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4) )
242  }
243 
244 
245  template< class XX
246  , typename P1
247  , typename P2
248  , typename P3
249  , typename P4
250  , typename P5
251  >
252  XX* //___________________
253  create (P1& p1, P2& p2, P3& p3, P4& p4, P5& p5)
254  {
255  _EXCEPTION_SAFE_INVOKE ( XX (p1,p2,p3,p4,p5) )
256  }
257 
258 #undef _EXCEPTION_SAFE_INVOKE
259 
260 
261 
262  template<class XX>
263  void
264  destroy (XX* entry)
265  {
266  if (!entry) return;
267  ___assertSupportedType<XX>();
268  try
269  {
270  entry->~XX();
271  }
272  catch(...)
273  {
274  lumiera_err errorID = lumiera_error();
275  WARN (common_dbg, "dtor of «%s» failed: %s", util::typeStr(entry).c_str()
276  , errorID );
277  }
278  releaseSlot<XX> (entry);
279  }
280 
281 
283  template<class XX>
284  size_t
285  numSlots() const
286  {
287  return COUNTER::template allocationCount<XX>();
288  }
289  };
290 
291 
292 
293 
294 } // namespace lib
295 #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:71
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:115
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.