Lumiera  0.pre.03
»edit your freedom«
tracking-allocator.hpp
Go to the documentation of this file.
1 /*
2  TRACKING-ALLOCATOR.hpp - custom allocator for memory management diagnostics
3 
4  Copyright (C)
5  2024, 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 
46 #ifndef LIB_TEST_TRACKING_ALLOCATOR_H
47 #define LIB_TEST_TRACKING_ALLOCATOR_H
48 
49 #include "lib/error.hpp"
50 #include "lib/symbol.hpp"
51 #include "lib/nocopy.hpp"
52 #include "lib/hash-value.h"
53 #include "lib/test/event-log.hpp"
54 #include "lib/format-string.hpp"
55 
56 #include <utility>
57 #include <memory>
58 
59 using std::byte;
60 
61 
62 namespace lib {
63 namespace test {
64 
65 
66  namespace {
67  const Symbol GLOBAL{"GLOBAL"};
68  }
69 
71  class MemoryPool;
72 
74 
75 
76 
84  {
85  PoolHandle mem_;
86 
87  public:
90 
93 
94  // standard copy operations acceptable
95 
96  using Location = void*;
97 
98  [[nodiscard]] Location allocate (size_t n);
99  void deallocate (Location, size_t =0) noexcept;
100 
101 
102  friend bool
103  operator== (TrackingAllocator const& a1, TrackingAllocator const& a2)
104  {
105  return a1.mem_ == a2.mem_;
106  }
107  friend bool
108  operator!= (TrackingAllocator const& a1, TrackingAllocator const& a2)
109  {
110  return not (a1 == a2);
111  }
112 
113 
114  /* ===== Diagnostics ===== */
115 
116  bool manages (Location) const;
117  size_t getSize(Location) const;
118  HashVal getID (Location) const;
119  Literal poolID () const;
120 
121  static HashVal checksum (Literal pool =GLOBAL);
122  static size_t use_count (Literal pool =GLOBAL);
123  static size_t numAlloc (Literal pool =GLOBAL);
124  static size_t numBytes (Literal pool =GLOBAL);
125 
126  static EventLog log;
127  };
128 
129 
138  template<typename TY>
140  : public TrackingAllocator
141  {
142  public:
144 
146  template<typename X>
147  TrackAlloc (TrackAlloc<X> const& anchor)
148  : TrackingAllocator{anchor}
149  { }
150 
151 
152  /* ===== C++ standard allocator interface ===== */
153 
154  using value_type = TY;
155 
156  // define that (non-equivalent) allocators migrate alongside on assignments....
157  using propagate_on_container_copy_assignment = std::true_type;
158  using propagate_on_container_move_assignment = std::true_type;
159  using propagate_on_container_swap = std::true_type;
160 
161 
162  [[nodiscard]] TY* allocate (size_t cnt);
163  void deallocate (TY*, size_t) noexcept;
164  };
165 
166 
167 
172  : public TrackingAllocator
173  {
174  public:
176 
179  : TrackingAllocator{anchor}
180  { }
181 
183  template<class TY, typename...ARGS>
184  TY*
185  create (ARGS&& ...args)
186  {
187  Location loc = allocate(sizeof(TY));
188  log.call (poolID(),"create-"+util::typeStr<TY>(), std::forward<ARGS> (args)...);
189  try {
190  return new(loc) TY (std::forward<ARGS> (args)...);
191  }
192  catch (std::exception& mishap)
193  {
194  log.error (util::_Fmt{"CtorFail: type=%s, problem:%s"} % util::typeStr<TY>() % mishap.what());
195  throw;
196  }
197  catch (...)
198  {
199  log.error ("CtorFail: unknown cause");
200  throw;
201  }
202  }
203 
205  template<class TY>
206  void
207  dispose (TY* elm) noexcept
208  {
209  if (not elm)
210  {
211  log.warn("dispose(nullptr)");
212  return;
213  }
214  log.call (poolID(),"destroy-"+util::typeStr<TY>());
215  elm->~TY();
216  deallocate(elm, sizeof(TY));
217  }
218  };
219 
220 
221 
225  template<typename TY>
226  TY*
228  {
229  return static_cast<TY*> (TrackingAllocator::allocate (cnt * sizeof(TY)));
230  }
231 
236  template<typename TY>
237  void
238  TrackAlloc<TY>::deallocate (TY* loc, size_t cnt) noexcept
239  {
240  TrackingAllocator::deallocate (loc, cnt * sizeof(TY));
241  }
242 
243 
244 
245 
246 }} // namespace lib::test
247 #endif /*LIB_TEST_TRACKING_ALLOCATOR_H*/
Location allocate(size_t n)
Allot a memory block of given size bytes.
static HashVal checksum(Literal pool=GLOBAL)
get Checksum for specific mem-pool
C++ standard compliant custom allocator adapter backed by the TrackingAllocator and the MemoryPool de...
size_t getSize(Location) const
retrieve the registered size of this allocation, if known.
EventLog & warn(string text)
Log a warning entry.
Definition: event-log.cpp:710
std::true_type propagate_on_container_swap
otherwise they would have to deallocate cross-wise
Support for verifying the occurrence of events from unit tests.
Definition: run.hpp:40
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
Helper to log and verify the occurrence of events.
Definition: event-log.hpp:275
Front-end for printf-style string template interpolation.
Generic low-level allocator attached to tracking MemoryPool.
static size_t numBytes(Literal pool=GLOBAL)
calculate currently allotted Bytes for mem-pool
TrackingFactory(TrackingAllocator const &anchor)
attach to the given TrackingAllocator and MemoryPool
bool manages(Location) const
probe if this allocator pool did allocate the given memory location
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Generic object factory backed by TrackingAllocator.
void dispose(TY *elm) noexcept
destroy the given element and discard the associated memory and registration
TY * create(ARGS &&...args)
create new element with an allocation registered in the backing MemoryPool
void deallocate(Location, size_t=0) noexcept
Discard and forget an allocation created through this allocator.
Token or Atom with distinct identity.
Definition: symbol.hpp:117
Mix-Ins to allow or prohibit various degrees of copying and cloning.
std::true_type propagate_on_container_copy_assignment
for sake of consistency
Marker types to indicate a literal string and a Symbol.
EventLog & call(string target, string function)
Log occurrence of a function call with no arguments.
Definition: event-log.cpp:690
HashVal getID(Location) const
retrieve the internal registration ID for this allocation.
TY * allocate(size_t cnt)
C++ standard allocator API : allot raw memory for cnt elements of type TY.
std::true_type propagate_on_container_move_assignment
otherwise all elements must be copied
Lumiera error handling (C++ interface).
void deallocate(TY *, size_t) noexcept
C++ standard allocator API : clear an existing allocation, which must have been allocated into the sa...
Hash value types and utilities.
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
static size_t numAlloc(Literal pool=GLOBAL)
get active allocation count for mem-pool
static size_t use_count(Literal pool=GLOBAL)
determine number of active front-end handles
TrackingAllocator()
can be default created to attach to a common pool
TrackAlloc(TrackAlloc< X > const &anchor)
cross-building for another type, using a common pool
EventLog & error(string text)
Log an error note.
Definition: event-log.cpp:717