41 #include <unordered_map> 44 using std::make_shared;
62 using Location =
void*;
65 HashVal operator() (Location
const& loc)
const {
return HashVal(loc); }
76 using AllocTab = std::unordered_map<const Location, Allocation, LocationHash>;
93 void discardAlloc (
void* loc,
size_t);
98 size_t getAllocationCnt()
const;
99 size_t calcAllocSize()
const;
101 Literal getPoolID()
const {
return poolID_; }
109 inline EventLog& log() {
return TrackingAllocator::log; }
111 template<
typename...XS>
113 logAlarm (XS
const& ...xs)
115 log().
error (joinDash(xs...));
118 template<
typename...ARGS>
120 logAlloc (
Literal pool,
string fun, ARGS
const& ...args)
122 log().
call (pool,fun,args...);
130 using PoolTab = std::unordered_map<Literal, std::weak_ptr<MemoryPool>>;
148 PoolRegistry::locate (
Literal poolID)
150 return poolReg().fetch_or_create (poolID);
155 PoolRegistry::fetch_or_create (
Literal poolID)
157 auto&
entry = pools_[poolID];
158 auto handle =
entry.lock();
159 if (handle)
return handle;
162 PoolHandle newPool = make_shared<MemoryPool> (poolID);
173 : mem_{PoolRegistry::locate(GLOBAL)}
177 : mem_{PoolRegistry::locate(
id)}
187 TrackingAllocator::Location
191 return mem_->addAlloc (bytes)
204 mem_->discardAlloc (loc, bytes);
208 MemoryPool::addAlloc (
size_t bytes)
211 newAlloc.buff.allocate (bytes);
212 Location loc = newAlloc.buff.front();
213 ASSERT (not contains (allocs_, loc));
214 newAlloc.entryID = ++entryNr_;
215 logAlloc (poolID_,
"allocate", bytes, newAlloc.entryID, showAdr(loc));
216 checksum_ += newAlloc.entryID * bytes;
217 return allocs_.emplace (loc, move(newAlloc))
222 MemoryPool::discardAlloc (Location loc,
size_t bytes)
224 if (contains (allocs_, loc))
226 auto&
entry = allocs_[loc];
228 ASSERT (
entry.buff.front() == loc);
229 if (
entry.buff.size() != bytes)
230 logAlarm (
"SizeMismatch", bytes,
"≠",
entry.buff.size(),
entry.entryID, showAdr(loc));
232 logAlloc (poolID_,
"deallocate", bytes,
entry.entryID, bytes, showAdr(loc));
233 checksum_ -=
entry.entryID * bytes;
237 logAlarm (
"FreeUnknown", bytes, showAdr(loc));
242 MemoryPool::findAlloc (Location loc)
const 244 return contains (allocs_, loc)? & allocs_.at(loc)
250 MemoryPool::getChecksum()
const 256 MemoryPool::getAllocationCnt()
const 258 return allocs_.size();
262 MemoryPool::calcAllocSize()
const 265 .transform ([](
auto& it){
return it->second.buff.size(); })
273 EventLog TrackingAllocator::log{
"test::TrackingAllocator"};
280 PoolHandle pool = PoolRegistry::locate (poolID);
281 return pool->getChecksum();
288 PoolHandle pool = PoolRegistry::locate (poolID);
289 return pool.use_count() - 1;
296 PoolHandle pool = PoolRegistry::locate (poolID);
297 return pool->getAllocationCnt();
304 PoolHandle pool = PoolRegistry::locate (poolID);
305 return pool->calcAllocSize();
314 return bool(mem_->findAlloc (memLoc));
322 auto*
entry = mem_->findAlloc (memLoc);
332 auto*
entry = mem_->findAlloc (memLoc);
338 TrackingAllocator::poolID()
const 341 return mem_->getPoolID();
Depend< MemoryPool > globalPool
singleton for default pool
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
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
size_t getSize(Location) const
retrieve the registered size of this allocation, if known.
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
Any copy and copy construction prohibited.
inline string literal This is a marker type to indicate that
Helper to log and verify the occurrence of events.
Types marked with this mix-in may be moved but not copied.
static size_t numBytes(Literal pool=GLOBAL)
calculate currently allotted Bytes for mem-pool
bool manages(Location) const
probe if this allocator pool did allocate the given memory location
Access point to singletons and other kinds of dependencies designated by type.
Implementation namespace for support and library code.
void deallocate(Location, size_t=0) noexcept
Discard and forget an allocation created through this allocator.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
EventLog & call(string target, string function)
Log occurrence of a function call with no arguments.
Unittest helper code: a custom allocator to track memory usage.
HashVal getID(Location) const
retrieve the internal registration ID for this allocation.
A raw memory block with proper alignment and array access.
Singleton services and Dependency Injection.
registration entry to maintain a single allocation
size_t HashVal
a STL compatible hash value
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
Building tree expanding and backtracking evaluations within hierarchical scopes.
keep track of any distinct memory pools used
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
EventLog & error(string text)
Log an error note.