From 73dd24ecef17ab31232d024c4631e4e1665e2c3e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 28 May 2024 04:03:51 +0200 Subject: [PATCH] Library: start design draft to replace `RefArray` Some decisions - use a single template with policy base - population via separate builder class - implemented similar to vector (start/end) - but able to hold larger (subclass) objects --- src/lib/several-builder.hpp | 119 ++------------ src/lib/several.hpp | 39 ++++- tests/library/several-builder-test.cpp | 214 +++++++++---------------- wiki/thinkPad.ichthyo.mm | 61 ++++++- 4 files changed, 171 insertions(+), 262 deletions(-) diff --git a/src/lib/several-builder.hpp b/src/lib/several-builder.hpp index ac172aa31..316782933 100644 --- a/src/lib/several-builder.hpp +++ b/src/lib/several-builder.hpp @@ -57,119 +57,24 @@ namespace lib { * Wrap a vector holding objects of a subtype and * provide array-like access using the interface type. */ - template - class RefArrayVectorWrapper - : public RefArray + template + class SeveralBuilder { - typedef vector const& Tab; - Tab table_; - + public: - - RefArrayVectorWrapper (Tab toWrap) - : table_(toWrap) - { } - - virtual size_t size() const + Several + build() { - return table_.size(); - } - - virtual B const& operator[] (size_t i) const - { - REQUIRE (i < size()); - return table_[i]; + UNIMPLEMENTED ("materialise into Several-Container"); } }; - - /** - * This variation of the wrapper actually - * \em is a vector, but can act as a RefArray - */ - template - class RefArrayVector - : public vector, - public RefArrayVectorWrapper - { - typedef RefArrayVectorWrapper Wrap; - typedef vector Vect; - typedef typename Vect::size_type Size_t; - typedef typename Vect::value_type Val_t; - - public: - RefArrayVector() : Vect(), Wrap((Vect&)*this) {} - RefArrayVector(Size_t n, Val_t const& v = Val_t()) : Vect(n,v), Wrap((Vect&)*this) {} - RefArrayVector(Vect const& ref) : Vect(ref), Wrap((Vect&)*this) {} - - using Vect::size; - using Wrap::operator[]; - }; - - - - /** - * RefArray implementation based on a fixed size array, - * i.e. the storage is embedded. Embedded subclass obj - * either need to be default constructible or be - * placed directly by a factory - */ - template - class RefArrayTable - : public RefArray - { - char storage_[n*sizeof(IM)]; - IM* array_; - - public: - RefArrayTable() ///< objects created in-place by default ctor - : array_ (reinterpret_cast (&storage_)) - { - size_t i=0; - try - { - while (i - RefArrayTable(FAC& factory) ///< objects created in-place by factory - : array_ (reinterpret_cast (&storage_)) - { - size_t i=0; - try - { - while (i + SeveralBuilder + makeSeveral (std::initializer_list ili) + { + UNIMPLEMENTED ("start building a Several-Container"); + } } // namespace lib diff --git a/src/lib/several.hpp b/src/lib/several.hpp index c3b19ac46..9786d9e31 100644 --- a/src/lib/several.hpp +++ b/src/lib/several.hpp @@ -45,18 +45,43 @@ namespace lib { * Typically the return type is an interface, * and the Implementation wraps some datastructure * holding subclasses. - * @todo ouch -- a collection that isn't iterable... ///////////////////////TICKET #1040 + * @todo ouch -- a collection that isn't iterable... ///////////////////////TICKET #1040 //////////OOO cookie jar * @warning in rework 5/2025 */ - template - class RefArray - : util::NonCopyable + template + class Several + : util::MoveOnly { public: - virtual ~RefArray() {} ///< this is an interface - virtual T const& operator[] (size_t i) const =0; - virtual size_t size() const =0; + size_t + size() const + { + UNIMPLEMENTED ("determine storage size"); + } + + I& + operator[] (size_t i) + { + UNIMPLEMENTED ("subscript"); + } + + I& + back() + { + UNIMPLEMENTED ("storage access"); + } + + using iterator = I*; + using const_iterator = I const*; + + iterator begin() { UNIMPLEMENTED ("iteration"); } + iterator end() { UNIMPLEMENTED ("iteration"); } + const_iterator begin() const { UNIMPLEMENTED ("iteration"); } + const_iterator end() const { UNIMPLEMENTED ("iteration"); } + + friend auto begin (Several const& svl) { return svl.begin();} + friend auto end (Several const& svl) { return svl.end(); } }; diff --git a/tests/library/several-builder-test.cpp b/tests/library/several-builder-test.cpp index dcb90a492..3545d1011 100644 --- a/tests/library/several-builder-test.cpp +++ b/tests/library/several-builder-test.cpp @@ -27,70 +27,64 @@ #include "lib/test/run.hpp" +#include "lib/test/testdummy.hpp" +#include "lib/test/test-helper.hpp" +#include "lib/test/diagnostic-output.hpp"////////////////TODO +#include "lib/iter-explorer.hpp" +#include "lib/format-util.hpp" #include "lib/util.hpp" #include "lib/several-builder.hpp" #include +#include using ::test::Test; using std::vector; using std::rand; +using lib::explore; +using util::join; + namespace lib { namespace test{ - - namespace { // test types + namespace { // diagnostic test types - struct I + /** + * Instance tracking sub-dummy + * - implements the Dummy interface + * - holds additional storage + * - specific implementation of the virtual operation + * - includes content of the additional storage into the + * checksum calculation, allowing to detect memory corruption + */ + template + class Num + : public test::Dummy { - virtual int op(int i) const =0; - virtual ~I() {} - }; - - struct Sub1 : I - { - int offs_; + std::array ext_; - Sub1 (int o=1) : offs_(o) {} - - int op (int i) const { return i+offs_; } - }; - - struct Sub2 : I - { - const char* letterz_; - Sub2() : letterz_("ABCDEFGHIJKLMNOPQRSTUVWXYZ") {} - - int op (int i) const { return (int)letterz_[i % 26]; } - }; - - struct Sub3 : I - { - int id_; - static long sum; - static long trigger; - - Sub3(int id) : id_(id) + public: + Num (uint seed=i) + : Dummy{seed} { - sum +=id_; - if ( id_ == trigger ) - throw trigger; // fail while in construction + ext_.fill(seed); + setVal ((i+1)*seed); } - ~Sub3() - { - sum -=id_; + ~Num() + { + setVal (getVal() - explore(ext_).resultSum()); + } + + long + acc (int ii) override + { + return i+ii + explore(ext_).resultSum(); } - - int op (int i) const { return i + id_; } }; - long Sub3::sum = 0; - long Sub3::trigger = -1; - - } // (END) test types @@ -100,15 +94,11 @@ namespace test{ /***************************************************************//** - * @test build several wrappers, each based on a different storage, - * all providing RefArray access to a given vector. The rationale - * for RefArray is to expose just the interface: the data structure - * within the actual implementation holds subclass instances of - * the specified interface. - * - RefArrayVectorWrapper is a ref to an existing vector - * - RefArrayVector subclasses std::vector - * - RefArrayTable holds a fix sized table, i.e. embedded storage - * + * @test use lib::Several to establish small collections of elements, + * possibly with sub-classing and controlled allocation. + * - the container is populated through a separate builder + * - the number of elements is flexible during population + * - the actual container allows random-access via base interface * @see several-builder.hpp */ class SeveralBuilder_test : public Test @@ -117,122 +107,62 @@ namespace test{ virtual void run (Arg) { - checkWrapper(); - checkVector(); - checkTable(); - checkTable_inplaceCreation(); - checkTable_errorHandling(); + simpleUsage(); + check_Builder(); + check_ErrorHandling(); + check_ElementAccess(); + check_CustomAllocator(); } + /** @test TODO demonstrate basic behaviour + * @todo WIP 5/24 🔁 define ⟶ implement + */ void - checkWrapper() + simpleUsage() { - vector subz(10); - RefArrayVectorWrapper subWrap (subz); - - RefArray & rArr (subWrap); - - CHECK (subWrap.size()==subz.size()); - CHECK (INSTANCEOF(I, &rArr[0])); - for (size_t i=0; i subz(10); - - vector & vect (subz); - RefArray & rArr (subz); - - CHECK (vect.size()==subz.size()); - CHECK (INSTANCEOF(I, &rArr[0])); - for (size_t i=0; i tab; - // creates 20 Sub1-objects in-place - // which are indeed located within the object - CHECK (sizeof(tab) >= 20 * sizeof(Sub1)); - CHECK (ADR(tab) < ADR(tab[19]) && ADR(tab[19]) < ADR(tab) + sizeof(tab)); - - RefArray & rArr (tab); - - CHECK (20 == tab.size()); - CHECK (INSTANCEOF(I, &rArr[0])); - for (size_t i=0; i - struct Fac ///< fabricating a series of subclass instances with varying ctor parameter - { - int offset_; - Fac ( ) : offset_ (0) {} - - void operator() (void* place) - { - CHECK (place); - new(place) SUB (offset_++); // note: varying ctor parameter - } - }; - + /** @test TODO verify access operations on the actual container + * @todo WIP 5/24 🔁 define ⟶ implement + */ void - checkTable_inplaceCreation() + check_ElementAccess() { - Fac theFact; - RefArrayTable tab (theFact); - RefArray & rArr (tab); - CHECK (30 == tab.size()); - for (size_t i=0; i factory; - RefArrayTable table (factory); - CHECK (Sub3::sum == (29+1)*29/2); - } - CHECK (Sub3::sum == 0); - } - - catch(long id) - { - CHECK (id == Sub3::trigger); - CHECK (Sub3::sum == id); - // meaning: all objects have been cleaned up, - // with the exception of the one hitting the trigger - } } } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 828610520..19cc53a97 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -81442,15 +81442,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + + +

- ...man verwendet nur speziell im produktiven Einsatz im Node-Graph  einen besonderen Allocator, der zwar den Destruktor aufruf, aber den Speicher nicht freigibt; alloziert wird immer in einen kompakten Block hinein, der dann auf der Basis der Prozeß-Kenntnis als Ganzes verworfen und neu verwendet wird. + ...man verwendet nur speziell im produktiven Einsatz im Node-Graph  einen besonderen Allocator, der zwar den Destruktor aufruft, aber den Speicher nicht freigibt; alloziert wird immer in einen kompakten Block hinein, der dann auf der Basis der Prozeß-Kenntnis als Ganzes verworfen und neu verwendet wird.

-
+ +
@@ -81661,9 +81664,56 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -81991,8 +82041,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
es gibt noch gar keine Verwendungen

- - +