From 54bd568714e62ceae07f3b2184a54453ff2f0669 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 8 Jun 2024 23:59:47 +0200 Subject: [PATCH] Library: integrate storage-management logic Parts of this logic were first coded down in the `realloc` template method, where it did not really belong; thus reintegrate similar logic one level above, in the SeveralBuilder::adjustStorage(). Moreover, for performance reasons, always start with an initial chunk, similar to what `std::vector` does... --- src/lib/several-builder.hpp | 98 +++++++++++++++++++----------- wiki/thinkPad.ichthyo.mm | 118 +++++++++++++++++++++++++++--------- 2 files changed, 149 insertions(+), 67 deletions(-) diff --git a/src/lib/several-builder.hpp b/src/lib/several-builder.hpp index 5129d6858..fde0cacfa 100644 --- a/src/lib/several-builder.hpp +++ b/src/lib/several-builder.hpp @@ -67,6 +67,12 @@ namespace lib { namespace {// Allocation management policies + /** number of storage slots to open initially; + * starting with an over-allocation similar to `std::vector` + */ + const uint INITIAL_ELM_CNT = 10; + + using util::max; using util::min; using util::_Fmt; @@ -357,22 +363,72 @@ namespace lib { } private: + template + void + emplaceCopy (IT& dataSrc) + { + using Val = std::remove_cv_t; + emplaceElm (*dataSrc); + } + + template + void + emplaceElm (ARGS&& ...args) + { + if (not handling_.template canDestroy()) + throw err::Invalid{_Fmt{"Unable to handle destructor for element type %s"} + % util::typeStr()}; + + // mark when target type is not trivially movable + handling_.template probeMoveCapability(); + + // ensure sufficient element capacity or the ability to adapt element spread + if (Coll::spread() < sizeof(TY) and not (Coll::empty() or handling_.canWildMove())) + throw err::Invalid{_Fmt{"Unable to place element of type %s (size=%d)" + "into container for element size %d."} + % util::typeStr() % sizeof(TY) % Coll::spread()}; + + size_t elmSiz = sizeof(TY); + size_t newPos = Coll::size(); + size_t newCnt = Coll::empty()? INITIAL_ELM_CNT : newPos+1; + adjustStorage (newCnt, max (elmSiz, Coll::spread())); + Coll::data_->cnt = newPos+1; + POL::template createAt (Coll::data_, newPos, forward (args)...); + } + + void adjustStorage (size_t cnt, size_t spread) { size_t demand{cnt*spread}; - Coll::data_ = POL::realloc (Coll::data_, cnt,spread); /////////////////OOO anpassen + size_t buffSiz{Coll::data_? Coll::data_->buffSiz : 0}; + if (demand == buffSiz) + return; + if (demand > buffSiz) + {// grow into exponentially expanded new allocation + size_t safetyLim = LUMIERA_MAX_ORDINAL_NUMBER * Coll::spread(); + size_t expandAlloc = min (safetyLim + ,max (2*buffSiz, demand)); + if (expandAlloc < demand) + throw err::State{_Fmt{"Storage expansion for Several-collection " + "exceeds safety limit of %d bytes"} % safetyLim + ,LERR_(SAFETY_LIMIT)}; + // allocate new storage block... + size_t newCnt = expandAlloc / spread; + if (newCnt * spread < expandAlloc) ++newCnt; + Coll::data_ = POL::realloc (Coll::data_, newCnt,spread); + } ENSURE (Coll::data_); - if (spread != Coll::spread()) + if (handling_.canWildMove() and spread != Coll::spread()) adjustSpread (spread); } void fitStorage() { - if (not Coll::data_) return; - size_t demand{Coll::size() * Coll::spread()}; - Coll::data_ = POL::realloc (Coll::data_, demand); + if (handling_.lock_move or not Coll::data_) + return; + Coll::data_ = POL::realloc (Coll::data_, Coll::size(), Coll::spread()); } /** move existing data to accommodate spread */ @@ -407,38 +463,6 @@ namespace lib { newPos += idx * newSpread; std::memmove (newPos, oldPos, util::min (oldSpread,newSpread)); } - - template - void - emplaceCopy (IT& dataSrc) - { - using Val = std::remove_cv_t; - emplaceElm (*dataSrc); - } - - template - void - emplaceElm (ARGS&& ...args) - { - if (not handling_.template canDestroy()) - throw err::Invalid{_Fmt{"Unable to handle destructor for element type %s"} - % util::typeStr()}; - - // mark when target type is not trivially movable - handling_.template probeMoveCapability(); - - // ensure sufficient element capacity or the ability to adapt element spread - if (Coll::spread() < sizeof(TY) and not (Coll::empty() or handling_.canWildMove())) - throw err::Invalid{_Fmt{"Unable to place element of type %s (size=%d)" - "into container for element size %d."} - % util::typeStr() % sizeof(TY) % Coll::spread()}; - - size_t elmSiz = sizeof(TY); - size_t newCnt = Coll::size()+1; - adjustStorage (newCnt, max (elmSiz, Coll::spread())); - Coll::data_->cnt = newCnt; - POL::template createAt (Coll::data_, newCnt-1, forward (args)...); - } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 59615e8ef..edefc4c88 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -82403,8 +82403,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -82414,52 +82414,104 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + + + + + + + + + + + + + + + + + + + +

+ oder es wird ausschließlich der Element-Typ E konstruiert +

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

+ Vorsicht: hab es aus der emplaceElm()-Funktion entfernt +

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

+ ...und das kann vom Allokator abhängen +

+ + +
+ +
+
+
+
+ - - - - - - - - - - - + - - - - - - - - - - - - + + + + + + - - + + + - - + + @@ -82655,6 +82707,12 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + +