From 72aea53ac352db81798d58fe7bb69796a042d835 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 17 May 2024 23:34:48 +0200 Subject: [PATCH] Library: idea for an extent management mechanism * this is pure old-style low-level trickery * using a layout trick, the `AllocationCluster` can be operated with the bare minimum of overhead * this trick relies on the memory layout of `lib::LinkedElements` --- src/lib/allocation-cluster.cpp | 143 +++++++++++++++++++++++++++++---- src/lib/allocation-cluster.hpp | 21 +++-- wiki/thinkPad.ichthyo.mm | 61 ++++++++++++++ 3 files changed, 206 insertions(+), 19 deletions(-) diff --git a/src/lib/allocation-cluster.cpp b/src/lib/allocation-cluster.cpp index cbf6ea039..5bce5860f 100644 --- a/src/lib/allocation-cluster.cpp +++ b/src/lib/allocation-cluster.cpp @@ -30,14 +30,110 @@ #include "lib/allocation-cluster.hpp" -#include "lib/error.hpp" +#include "lib/linked-elements.hpp" #include "lib/util.hpp" +#include +#include using util::isnil; namespace lib { + namespace {// Configuration constants + const size_t EXTENT_SIZ = 256; + const size_t OVERHEAD = 2 * sizeof(void*); + const size_t STORAGE_SIZ = EXTENT_SIZ - OVERHEAD; + + using HeapAlloc = std::allocator; + using Alloc = std::allocator_traits; + + HeapAlloc heap; + + void* + allocate (size_t bytes) + { + return Alloc::allocate (heap, bytes); + } + + void + destroy (void* storage) + { + Alloc::destroy (heap, static_cast (storage)); + } + } + + /** + * An _overlay view_ for the AllocationCluster to add functionality + * for adding / clearing extents and registering optional deleter functions. + * @warning this is a tricky construct to operate each Allocation Cluster + * with the absolute necessary minimum of organisational overhead. + * The key point to note is that StorageManager is layout compatible + * with AllocationCluster itself — achieved through use of the union + * ManagementView, which holds a Storage descriptor member, but + * also an alternate view to manage a chain of extents as + * intrusive linked list (lib::LinkedElements). + * @remark this trick relies on `std::align(pos,rest)` to manage the storage + * coordinates coherently, allowing to re-establish the begin + * of each storage block always, using pointer arithmetics. + */ + class AllocationCluster::StorageManager + { + struct Destructor + { + Destructor* next; + ///////////////////////////////////////////////OOO store deleter function here + }; + using Destructors = lib::LinkedElements; + + struct Extent + { + Extent* next; + Destructors dtors; + std::byte storage[STORAGE_SIZ]; + }; + using Extents = lib::LinkedElements; + + union ManagementView + { + Storage storage{}; + Extents extents; + }; + + ManagementView view_; + + public: + static StorageManager& + access (AllocationCluster& clu) + { + return reinterpret_cast (clu); + } + + void + addBlock() + { + closeCurrentBlock(); + prependNextBlock(); + } + + private: + void + closeCurrentBlock() + { + ASSERT (view_.storage.pos); + // relocate the pos-pointer to the start of the block + view_.storage.pos += view_.storage.rest - EXTENT_SIZ; + view_.storage.rest = 0; + } + + void + prependNextBlock() + { + view_.extents.emplace(); + view_.storage.pos = & view_.extents.top().storage; + view_.storage.rest = STORAGE_SIZ; + } + }; @@ -46,30 +142,49 @@ namespace lib { * is managed by a separate instance of the low-level memory manager. */ AllocationCluster::AllocationCluster() - { - TRACE (memory, "new AllocationCluster"); - } + { + TRACE (memory, "new AllocationCluster"); + } /** On shutdown of the AllocationCluster we need to assure a certain * destruction order is maintained by explicitly invoking a cleanup - * operation on each of the low-level memory manager objects. + * operation on each of the low-level memory manager objects. */ AllocationCluster::~AllocationCluster() noexcept - { - try - { - - TRACE (memory, "shutting down AllocationCluster"); - - } - ERROR_LOG_AND_IGNORE (progress, "discarding AllocationCluster") - } + try + { + + TRACE (memory, "shutting down AllocationCluster"); + + } + ERROR_LOG_AND_IGNORE (progress, "discarding AllocationCluster") + /** + * Expand the alloted storage pool by a block, + * suitable to accommodate at least the indicated request. + * @remark Storage blocks are organised as linked list, + * allowing to de-allocate all blocks together. + */ + void + AllocationCluster::expandStorage (size_t allocRequest) + { + ENSURE (allocRequest + OVERHEAD <= EXTENT_SIZ); + void* newBlock = allocate (EXTENT_SIZ); ////////////////////////OOO obsolete ... use ManagementView instead!!! + StorageManager::access(*this).addBlock(); + } + + /* === diagnostics helpers === */ + bool + AllocationCluster::_is_within_limits (size_t size, size_t align) + { + UNIMPLEMENTED ("size limits"); ///////////////////////////OOO enforce maximum size limits + } + } // namespace lib diff --git a/src/lib/allocation-cluster.hpp b/src/lib/allocation-cluster.hpp index 330381c4c..627f598b2 100644 --- a/src/lib/allocation-cluster.hpp +++ b/src/lib/allocation-cluster.hpp @@ -97,9 +97,15 @@ namespace lib { AllocationCluster* mother_; }; - /* maintaining the Allocation */ - void* storage_; - size_t remain_; + class StorageManager; + + /** maintaining the Allocation */ + struct Storage + { + void* pos{nullptr}; + size_t rest{0}; + }; + Storage storage_; public: AllocationCluster (); @@ -144,10 +150,12 @@ namespace lib { void* allotMemory (size_t bytes, size_t alignment) { - void* loc = std::align(alignment, bytes, storage_, remain_); + ENSURE (_is_within_limits (bytes, alignment)); + void* loc = std::align (alignment, bytes, storage_.pos, storage_.rest); if (loc) return loc; - UNIMPLEMENTED ("actual memory management"); + expandStorage (bytes); + return allotMemory (bytes, alignment); ///////////////////////////////////////////////////////////OOO claim next macro block } @@ -157,6 +165,9 @@ namespace lib { { return static_cast (allotMemory (cnt * sizeof(X), alignof(X))); } + + void expandStorage (size_t); + bool _is_within_limits (size_t,size_t); }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 01cf0c594..6e2ddef12 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81697,6 +81697,20 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ alignof()-Operator und die Hilfsfunktion std::align() +

+ + +
+ +
@@ -81730,6 +81744,53 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + +

+ auch: eine gradzahlige Anzahl an Overhead-Slots +

+ + +
+
+ + + + + + +

+ ...durch diesen Trick sparen wir uns einen zusätzlichen Pointer auf den aktuellen Block: da std::allign(pos,rest) den pos-Zeiger stets kohärent zusammen mit dem rest-cnt manipuliert, können wir stets aus beiden zusammen wieder zum Anfang des Blocks zurückfinden. +

+ + +
+
+ + + + + + + + + + + + + + + +