diff --git a/src/lib/test/tracking-allocator.cpp b/src/lib/test/tracking-allocator.cpp index bcc3acc7d..5d6065713 100644 --- a/src/lib/test/tracking-allocator.cpp +++ b/src/lib/test/tracking-allocator.cpp @@ -37,44 +37,130 @@ //#include "lib/unique-malloc-owner.hpp" #include "lib/depend.hpp" #include "lib/uninitialised-storage.hpp" +#include "lib/util.hpp" //#include +#include //using util::_Fmt; +using std::make_shared; +using std::make_pair; //using std::string; +using util::contains; +using util::joinDash; namespace lib { namespace test{ + + /** + * @internal registration and tracking of memory allocations handed out. + */ + class MemoryPool + : util::NonCopyable + { + // using the allocated memory location as key + using Location = void*; + struct LocationHash + { + HashVal operator() (Location const& loc) const { return HashVal(loc); } + }; + + /** registration entry to maintain a single allocation */ + struct Allocation + : util::MoveOnly + { + UninitialisedDynBlock buff{}; + }; + + using AllocTab = std::unordered_map; + + + Literal poolID_; + AllocTab allocs_{}; + + public: + MemoryPool (Literal id) + : poolID_{id} + , allocs_{} + { } + + Allocation& addAlloc (size_t bytes); + void discardAlloc (void* loc); + }; + + namespace { // implementation details for common memory management - struct Allocation - { - UninitialisedDynBlock buff; - }; + /* === Logging primitives === */ - /** - * @internal registration and tracking of memory allocations handed out. - */ - class MemoryPool + inline EventLog& log() { return TrackingAllocator::log; } + + template + inline void + logAlarm (XS const& ...xs) + { + log().error (joinDash(xs...)); + } + + template + inline void + logAlloc (Literal pool, string fun, ARGS const& ...args) + { + log().call (pool,fun,args...); + } + + + class PoolRegistry + : util::NonCopyable { + std::unordered_map> pools_{}; + public: + static PoolHandle locate (Literal poolID); + + private: + PoolHandle fetch_or_create (Literal poolID); }; Depend globalPool; - } - - + Depend poolReg; + + + /** static access front-end : locate (or create) a MemoryPool */ + PoolHandle + PoolRegistry::locate (Literal poolID) + { + return poolReg().fetch_or_create (poolID); + } + + + PoolHandle + PoolRegistry::fetch_or_create (Literal poolID) + { + auto entry = pools_[poolID]; + auto handle = entry.lock(); + if (handle) return handle; + + // create a new pool and enrol it for given ID + PoolHandle newPool = make_shared (poolID); + entry = newPool; + return newPool; + } + }//(End)Implementation memory pools and registration + + + + + TrackingAllocator::TrackingAllocator() - : mem_{} + : mem_{PoolRegistry::locate(GLOBAL)} { } TrackingAllocator::TrackingAllocator (Literal id) - : mem_{} - { - UNIMPLEMENTED ("attach to specific pool"); - } + : mem_{PoolRegistry::locate(id)} + { } void* @@ -89,11 +175,38 @@ namespace test{ UNIMPLEMENTED ("allocate memory block of size n"); } + MemoryPool::Allocation& + MemoryPool::addAlloc (size_t bytes) + { + Allocation newAlloc; + newAlloc.buff.allocate (bytes); + Location loc = newAlloc.buff.front(); + ASSERT (not contains (allocs_, loc)); + logAlloc (poolID_, "allocate", bytes, loc); + return allocs_.emplace (loc, move(newAlloc)) + .first->second; + } + + void + MemoryPool::discardAlloc (void* loc) + { + if (contains (allocs_, loc)) + { + auto& entry = allocs_[loc]; + ASSERT (entry.buff); + ASSERT (entry.buff.front() == loc); + logAlloc (poolID_, "deallocate", entry.buff.size()); + allocs_.erase(loc); + } + else // deliberately no exception here (for better diagnostics) + logAlarm("FreeUnknown", loc); + } + /* ===== Diagnostics ===== */ - EventLog TrackingAllocator::log{"test::TrackingAllocator"}; + EventLog TrackingAllocator::log{"test::TrackingAllocator"}; HashVal diff --git a/src/lib/test/tracking-allocator.hpp b/src/lib/test/tracking-allocator.hpp index 7a8484884..26b936820 100644 --- a/src/lib/test/tracking-allocator.hpp +++ b/src/lib/test/tracking-allocator.hpp @@ -48,19 +48,21 @@ using std::byte; namespace lib { namespace test { - - namespace { // common memory management for the TrackingAllocator - + + namespace { const Symbol GLOBAL{"GLOBAL"}; - - /** common registration table and memory pool */ - class MemoryPool; } + /** common registration table and memory pool */ + class MemoryPool; + + using PoolHandle = std::shared_ptr; + + class TrackingAllocator { - std::shared_ptr mem_; + PoolHandle mem_; public: /** can be default created to attach to a common pool */ @@ -94,7 +96,7 @@ namespace test { static size_t numAlloc (Literal pool =GLOBAL); static size_t numBytes (Literal pool =GLOBAL); - static EventLog log; + static EventLog log; }; @@ -113,7 +115,7 @@ namespace test { /* ===== C++ standard allocator interface ===== */ - + using value_type = TY; [[nodiscard]] TY* allocate (size_t cnt); @@ -122,7 +124,7 @@ namespace test { /** - * + * C++ standard allocator API : allot raw memory for \a cnt elements of type \a TY */ template TY* @@ -132,7 +134,8 @@ namespace test { } /** - * + * C++ standard allocator API : clear an existing allocation, + * which must have been allocated into the same pool, with given element cnt. */ template void diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 686e49ac3..d888ae570 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -83582,29 +83582,59 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + + + - - + + + + + + +

+ verwende die Speicheradresse direkt als Hash-Wert; muß dazu eine Hasher-Funktion implementieren und in den Typ der Hashtable aufnehmen +

+ + +
+
- - + + - - + + + + + + + + + + + + + + + + + + +