Block-Flow: implement cyclic usage of an extent pool

..with the ability to grow on demand..
..possibly add the new extents in the middle, by first allocating at the end
  and then using the std::rotate() algo to bring them to the point
  in the middle where new extents are required
This commit is contained in:
Fischlurch 2023-07-10 05:40:50 +02:00
parent c1b16349f2
commit e86cb017a5
2 changed files with 137 additions and 22 deletions

View file

@ -32,7 +32,7 @@
** and down to avoid holding larger amounts of unused memory, while the availability
** of a baseline amount of memory can be enforced.
**
** @see ////TODO_test usage example
** @see ExtentFamily_test
** @see gear::BlockFlow usage example
**
** @todo WIP-WIP-WIP 7/2023 »Playback Vertical Slice«
@ -51,6 +51,7 @@
//#include "lib/util.hpp"
//#include <string>
#include <algorithm>
#include <memory>
#include <vector>
#include <array>
@ -68,12 +69,17 @@ namespace mem {
/**
* Memory manager to provide a sequence of Extents for cyclic usage.
* @todo WIP-WIP 7/2023
* @see NA_test
* @see ExtentFamily_test
*/
template<typename T, size_t siz>
class ExtentFamily
: util::NonCopyable
{
/** number of excess new extents
* to add whenever new storage is required
*/
static const size_t EXCESS_ALLOC{5};
public:
struct Extent
: std::array<T,siz>
@ -108,6 +114,8 @@ namespace mem {
using RawIter = typename Extents::iterator;
/* ==== Management Data ==== */
Extents extents_;
size_t start_,after_;
@ -125,17 +133,42 @@ namespace mem {
extents_.reserve (expectedMaxExtents);
}
/** claim next \a cnt extents, possibly allocate.
* @note always allocating slightly in excess
*/
void
openNew (size_t cnt)
{
UNIMPLEMENTED ("claim next cnt extents, possibly allocate");
if (not canAccomodate (cnt))
{//insufficient reserve -> allocate
size_t oldSiz = extents_.size();
size_t addSiz = cnt - freeSlotCnt()
+ EXCESS_ALLOC;
// add a strike of new extents at the end
extents_.resize (oldSiz + addSiz);
if (isWrapped())
{// need the new elements in the middle, before the existing start_
auto p = extents_.begin();
auto first = p + start_;
auto mid = p + oldSiz;
auto last = p + oldSiz + addSiz;
// relocate [fist..mid) after [mid..last)
std::rotate (first, mid, last);
start_ += addSiz;
}
}
// now sufficient reserve extents are available
ENSURE (canAccomodate (cnt));
incWrap (after_, cnt);
}
/** discard oldest \a cnt extents */
void
dropOld (size_t cnt)
{
UNIMPLEMENTED ("discard oldest cnt extents");
}
REQUIRE (cnt <= activeSlotCnt());
incWrap (start_, cnt);
} ////////////////////////////////////////////////////////////////////////////TICKET #1316 : should reduce excess allocation (with apropriate damping to avoid oscillations)
/** allow transparent iteration of Extents, expanding storage on demand */
@ -149,6 +182,49 @@ namespace mem {
}
private:
bool
isWrapped() const
{
return after_ < start_;
} // note: both are equal only when empty
/** @return number of allocated slots actually used */
size_t
activeSlotCnt() const
{
REQUIRE (start_ <= extents_.size());
REQUIRE (after_ <= extents_.size());
return not isWrapped()? after_ - start_
: (after_ - 0)
+(extents_.size() - start_);
}
size_t
freeSlotCnt() const
{ // always keep one in reserve...
REQUIRE (activeSlotCnt() < extents_.size());
return extents_.size() - activeSlotCnt();
}
bool
canAccomodate (size_t addCnt) const
{
return addCnt < freeSlotCnt(); // keep one in reserve
}
/** increment index, but wrap at array end.
* @remark using the array cyclically
*/
void
incWrap (size_t& idx, size_t inc)
{
idx = (idx+inc) % extents_.size();
}
/* == Iteration control API (used by IterAdapter via ADL) == */
friend bool
@ -163,11 +239,19 @@ namespace mem {
UNIMPLEMENTED ("ExtentFamily iteration control: access next Extent, possibly expand allocation");
}
/// „backdoor“ to watch internals from tests
friend class ExtentDiagnostic<T,siz>;
};
/* ===== Test / Diagnostic ===== */
template<typename T, size_t siz>
struct ExtentDiagnostic
{
@ -178,7 +262,7 @@ namespace mem {
size_t first() { return exFam_.start_; }
size_t last() { return exFam_.after_; }
size_t size() { return exFam_.extents_.size(); }
size_t active() { UNIMPLEMENTED ("count active"); }
size_t active() { return exFam_.activeSlotCnt(); }
};
template<typename T, size_t siz>

View file

@ -78517,8 +78517,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1688434743454" ID="ID_722620082" MODIFIED="1688434762609" TEXT="ExtentFamily erzeugen mit pre-Allocation">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1688862941032" ID="ID_1514279635" MODIFIED="1688868055421" TEXT="Diagnose der tats&#xe4;chlichen Speicherbelegung">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1688862941032" ID="ID_1514279635" MODIFIED="1688960119406" TEXT="Diagnose der tats&#xe4;chlichen Speicherbelegung">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688863035539" ID="ID_557979292" MODIFIED="1688864962621" TEXT="belegen und Aufr&#xe4;umen">
@ -78783,8 +78783,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688337270626" ID="ID_1810148055" MODIFIED="1688337284937" TEXT="&#xbb;BlockFlow&#xab; : Implementation">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398675985" ID="ID_291772625" MODIFIED="1688398683406" TEXT="Basis: ExtentFamily">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1688398675985" ID="ID_291772625" MODIFIED="1688960090391" TEXT="Basis: ExtentFamily">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398685028" ID="ID_1348599303" MODIFIED="1688398807927" TEXT="Anforderungen">
<icon BUILTIN="yes"/>
<node CREATED="1688398688699" ID="ID_1432998672" MODIFIED="1688398701914" TEXT="stellt eine Sequenz von &#xbb;Extents&#xab; bereit"/>
@ -78808,9 +78808,9 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<icon BUILTIN="hourglass"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398813243" ID="ID_504623704" MODIFIED="1688398863035" TEXT="Aufbau testgetrieben...">
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1688398813243" ID="ID_504623704" MODIFIED="1688960080656" TEXT="Aufbau testgetrieben...">
<arrowlink COLOR="#eb4070" DESTINATION="ID_1132827905" ENDARROW="Default" ENDINCLINATION="-593;73;" ID="Arrow_ID_709934622" STARTARROW="None" STARTINCLINATION="-214;-18;"/>
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1688398884005" ID="ID_1188543253" MODIFIED="1688867997850" TEXT="Basis-Struktur">
<icon BUILTIN="button_ok"/>
<node CREATED="1688432746255" ID="ID_880122043" MODIFIED="1688432851088" TEXT="Entscheidung: die Gr&#xf6;&#xdf;e ist eine compile-time-Konstante">
@ -78949,18 +78949,49 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688398893220" ID="ID_675575195" MODIFIED="1688398901316" TEXT="belegen / freigeben">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437691137" ID="ID_292063242" MODIFIED="1688437712023" TEXT="pr&#xfc;fen auf ausreichende Reserve">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1688398893220" ID="ID_675575195" MODIFIED="1688960070966" TEXT="belegen / freigeben">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1688952897933" ID="ID_832611581" MODIFIED="1688955651916" TEXT="freie Reserve ermitteln">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437762175" ID="ID_1456790340" MODIFIED="1688437794274" TEXT="sonst: Allokation erweitern">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437770295" ID="ID_867206595" MODIFIED="1688437792757" TEXT="falls am Ende">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1688437691137" ID="ID_292063242" MODIFIED="1688960068981" TEXT="pr&#xfc;fen auf ausreichende Reserve">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1688437784470" ID="ID_797852741" MODIFIED="1688437792758" TEXT="falls wrap-around">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1688437762175" ID="ID_1456790340" MODIFIED="1688960067652" TEXT="sonst: Allokation erweitern">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1688437770295" ID="ID_867206595" MODIFIED="1688960066248" TEXT="falls am Ende">
<icon BUILTIN="button_ok"/>
<node CREATED="1688957825760" ID="ID_376842621" MODIFIED="1688957834883" TEXT="vector::resize() gen&#xfc;gt"/>
</node>
<node COLOR="#338800" CREATED="1688437784470" ID="ID_797852741" MODIFIED="1688960065205" TEXT="falls wrap-around">
<icon BUILTIN="button_ok"/>
<node CREATED="1688957839759" ID="ID_671792490" MODIFIED="1688957862703" TEXT="zus&#xe4;tzlich die neuen Elemente in die Pufferzone in der Mitte rotieren"/>
<node CREATED="1688957863500" ID="ID_592181743" MODIFIED="1688958053349" TEXT="std::rotate() verwenden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...dieser tauscht per std::swap aus; und zwar rekursiv inkrementell: erst das Segment vom Ende an den Anfang und dann rekursiv wieder std::rotate f&#252;r den Rest. Komplexit&#228;t: linear
</p>
</body>
</html></richcontent>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1688958797642" ID="ID_205839494" MODIFIED="1688958807300" TEXT="&#xdc;berschu&#xdf; freigeben">
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1688958808347" ID="ID_1777900061" MODIFIED="1688958867924" TEXT="Gefahr von Oszillationen &#x27f9; vorerst noch nicht implementiert">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1688958965134" ID="ID_559031085" MODIFIED="1688958983164" TEXT="vorerst w&#xe4;chst die Allokation nur">
<icon BUILTIN="clanbomber"/>
</node>
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1688958894805" ID="ID_1746833075" MODIFIED="1688958904528" TEXT="#1316 regulate Scheduler memory allocation">
<icon BUILTIN="hourglass"/>
<node CREATED="1688958915756" ID="ID_292339303" MODIFIED="1688958930662" TEXT="man m&#xfc;&#xdf;te einen typischen / durchschnittlichen Bedarf etablieren"/>
<node CREATED="1688958931778" ID="ID_764223223" MODIFIED="1688958942454" TEXT="und dann mit einer gewissen D&#xe4;mpfung darauf hinsteuern"/>
</node>
</node>
</node>