From 8923d0f7b5907cdb5d49c1d0ee9063e5fca79ee5 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 20 Dec 2024 01:47:40 +0100 Subject: [PATCH] Invocation: handle default case with disabled ''parameter functor'' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some further tweaks to the logic to allow using the `FeedPrototype` in the default setup, where ''nothing shall be done with parameters...'' Provide the basic constructors and a type constructor in FeedManifold, so that it is possible to install a ''processing functor'' into the prototype and then drop off a copy into each new `FeedManifold` With this additions, can now **demonstrate simple usage** __Remark__: using the `DiagnosticBufferProvider` developed several years ago; Seems to work well; however, when creating a new instance in the next test case, we get a hard failure when the previous test case did not discard all buffers. Not sure what to think about that * for one, it is good to get an alarm, since actually there should not be any leak * but on the other hand, `reset()` does imply IMHO „I want a clean slate“ Adding some code thus to clean out memory blocks marked as used. When a test wants to check that all memory was released, there are tools to do so. --- .../engine/diagnostic-buffer-provider.cpp | 2 + src/steam/engine/feed-manifold.hpp | 59 +++- .../engine/tracking-heap-block-provider.cpp | 29 +- .../engine/tracking-heap-block-provider.hpp | 6 +- tests/core/steam/engine/node-base-test.cpp | 46 ++- wiki/thinkPad.ichthyo.mm | 281 +++++++++++++++--- 6 files changed, 359 insertions(+), 64 deletions(-) diff --git a/src/steam/engine/diagnostic-buffer-provider.cpp b/src/steam/engine/diagnostic-buffer-provider.cpp index 3319b4f16..82429073f 100644 --- a/src/steam/engine/diagnostic-buffer-provider.cpp +++ b/src/steam/engine/diagnostic-buffer-provider.cpp @@ -67,6 +67,8 @@ namespace engine { TrackingHeapBlockProvider& DiagnosticBufferProvider::reset() { + if (pImpl_) + pImpl_->markAllEmitted(); pImpl_.reset(new TrackingHeapBlockProvider()); return *pImpl_; } diff --git a/src/steam/engine/feed-manifold.hpp b/src/steam/engine/feed-manifold.hpp index 0d5383ca9..aef6200ba 100644 --- a/src/steam/engine/feed-manifold.hpp +++ b/src/steam/engine/feed-manifold.hpp @@ -115,6 +115,7 @@ namespace engine { using lib::meta::is_Structured; using lib::meta::forEachIDX; using lib::meta::ElmTypes; + using lib::meta::NullType; using lib::meta::Tagged; using lib::meta::TySeq; using std::declval; @@ -265,7 +266,10 @@ namespace engine { using Param = std::conditional_t>; template - using isSuitable = std::is_constructible (std::declval()))>; + using Res = typename _Fun::Ret; + + template + using isSuitable = std::is_constructible>; template using isConfigurable = std::is_constructible; @@ -282,12 +286,25 @@ namespace engine { } return false; } + + + template + static constexpr bool isParamFun() { return isSuitable(); } + template + static constexpr bool canActivate() { return isSuitable() and isConfigurable(); } + }; + + /// a function of total void + struct _Disabled + { + void operator() (void) const {/*I do make a difference, I really do!*/} }; }//(End)Introspection helpers. - + template + class FeedPrototype; /** * Configuration context for a FeedManifold. @@ -330,7 +347,9 @@ namespace engine { { Param param; - ParamStorage() = default; + ParamStorage() + : param{} + { } template ParamStorage (INIT&& ...paramInit) @@ -356,7 +375,7 @@ namespace engine { using enable_if_hasParam = typename lib::meta::enable_if_c<_ProcFun::hasParam()>::type; template - using NotProvided = Tagged; + using NotProvided = Tagged; template using Provide_if = std::conditional_t>; @@ -459,6 +478,14 @@ namespace engine { static constexpr bool hasParam() { return _S::hasParam(); } + /** + * cross-builder: _Prototype_ can be used to attach parameter-provider-functors + * and then to create several further FeedManifold instances. + */ + using Prototype = FeedPrototype; + + + template auto& accessArg (ARG& arg) @@ -519,7 +546,7 @@ namespace engine { * The Processing-Functor will be copied into the actual FeedManifold instance * for each Node invocation. * @tparam FUN type of the data processing-functor - * @tparam PAM type of an optional parameter-setup functor + * @tparam PAM type of an optional parameter-setup functor (defaults to deactivated) */ template class FeedPrototype @@ -531,15 +558,33 @@ namespace engine { FUN procFun_; PAM paramFun_; + public: + FeedPrototype (FUN&& proc) + : procFun_{move (proc)} + , paramFun_{} + { } + + FeedPrototype (FUN&& proc, PAM&& par) + : procFun_{move (proc)} + , paramFun_{move (par)} + { } + // default move acceptable : pass pre-established setup + + static constexpr bool hasParam() { return _Trait::hasParam(); } + static constexpr bool hasParamFun() { return _Trait::template isParamFun(); } + static constexpr bool canActivate() { return _Trait::template canActivate(); } + + /** + * build suitable Feed(Manifold) for processing Node invocation + */ Feed createFeed (TurnoutSystem& turnoutSys) { - if constexpr (_Trait::hasParam()) + if constexpr (hasParamFun()) if (_Trait::isActivated(paramFun_)) return Feed{paramFun_(turnoutSys), procFun_}; return Feed{procFun_}; } - ///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1386 : elaborate setup / binding for parameter-creation }; diff --git a/src/steam/engine/tracking-heap-block-provider.cpp b/src/steam/engine/tracking-heap-block-provider.cpp index 16404e613..18e5d4b5d 100644 --- a/src/steam/engine/tracking-heap-block-provider.cpp +++ b/src/steam/engine/tracking-heap-block-provider.cpp @@ -43,7 +43,7 @@ namespace engine { using Buff = StreamType::ImplFacade::DataBuffer; - namespace { // implementation helpers... + namespace { // implementation helpers... inline Buff* asBuffer(void* mem) @@ -130,11 +130,19 @@ namespace engine { "allocation pool. This might lead to Segfault and memory leaks."); } + /** mark all managed blocks as disposed */ + void + discard() + { + if (blockList_) + for (Block& block : *blockList_) + block.markReleased(); + } - uint + uint prepare_for (uint number_of_expected_buffers) { - if (maxAllocCount_ && + if (maxAllocCount_ && maxAllocCount_ < blockList_->size() + number_of_expected_buffers) { ASSERT (maxAllocCount_ >= blockList_->size()); @@ -155,7 +163,7 @@ namespace engine { Block* find (void* blockLocation) { - return pick_Block_by_storage (*blockList_, blockLocation); + return pick_Block_by_storage (*blockList_, blockLocation); } @@ -205,8 +213,8 @@ namespace engine { }; } - - + + namespace { // Details of allocation and accounting const uint MAX_BUFFERS = 50; @@ -282,7 +290,14 @@ namespace engine { { return outSeq_.size(); } - + + void + TrackingHeapBlockProvider::markAllEmitted() + { + for (auto& [_, blockPool] : *pool_) + blockPool.discard(); + } + diagn::Block& TrackingHeapBlockProvider::access_emitted (uint bufferID) { diff --git a/src/steam/engine/tracking-heap-block-provider.hpp b/src/steam/engine/tracking-heap-block-provider.hpp index 3d75f7d1b..2eec152f2 100644 --- a/src/steam/engine/tracking-heap-block-provider.hpp +++ b/src/steam/engine/tracking-heap-block-provider.hpp @@ -120,7 +120,7 @@ namespace engine { : public BufferProvider { unique_ptr pool_; - ScopedPtrVect outSeq_; + ScopedPtrVect outSeq_; public: /* === BufferProvider interface === */ @@ -141,11 +141,13 @@ namespace engine { template TY& accessAs (uint bufferID); + void markAllEmitted(); + private: bool withinOutputSequence (uint bufferID) const; diagn::BlockPool& getBlockPoolFor (HashVal typeID); diagn::Block* locateBlock (HashVal typeID, void*); - diagn::Block* searchInOutSeqeuence (void* storage); + diagn::Block* searchInOutSeqeuence (void* storage); }; diff --git a/tests/core/steam/engine/node-base-test.cpp b/tests/core/steam/engine/node-base-test.cpp index 5bf21eba2..7ac87019d 100644 --- a/tests/core/steam/engine/node-base-test.cpp +++ b/tests/core/steam/engine/node-base-test.cpp @@ -62,6 +62,7 @@ namespace test { seedRand(); verify_TurnoutSystem(); verify_FeedManifold(); + verify_FeedPrototype(); UNIMPLEMENTED ("build a simple render node and then activate it"); } @@ -288,7 +289,7 @@ namespace test { //______________________________________ // Example-5: simple parameter and output - auto fun_singleParamOut = [&](short param, Buffer* buff) { *buff = param-1; }; + auto fun_singleParamOut = [](short param, Buffer* buff) { *buff = param-1; }; using M5 = FeedManifold; CHECK (not M5::hasInput()); CHECK ( M5::hasParam()); @@ -310,6 +311,49 @@ namespace test { m5.invoke(); CHECK (*oa1 == r2 - 1); // processing has placed result based on param into output buffer + + // done with these buffers + buffI0.release(); + buffI1.release(); + buffI2.release(); + buffO0.release(); + buffO1.release(); + } + + + + /** @test Setup of a FeeManifold to attach parameter-functors + */ + void + verify_FeedPrototype() + { + // Prepare setup to build a suitable FeedManifold... + long r1 = rani(100); + using Buffer = long; + BufferProvider& provider = DiagnosticBufferProvider::build(); + BuffHandle buff = provider.lockBufferFor (-55); + + auto fun_singleParamOut = [](short param, Buffer* buff) { *buff = param-1; }; + using M1 = FeedManifold; + using P1 = M1::Prototype; + CHECK ( P1::hasParam()); + CHECK (not P1::hasParamFun()); + CHECK (not P1::canActivate()); + + P1 p1{move (fun_singleParamOut)}; + CHECK (sizeof(p1) <= sizeof(void*)); + TurnoutSystem turSys{Time::NEVER}; + + M1 m1 = p1.createFeed(turSys); + CHECK (m1.param == short{}); + m1.outBuff.createAt(0, buff); + CHECK (buff.accessAs() == -55); + m1.connect(); + CHECK (*m1.outArgs == -55); + + m1.invoke(); + CHECK (*m1.outArgs == 0 - 1); + CHECK (buff.accessAs() == 0 - 1); } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 16bcbd002..48c107c6b 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -26631,9 +26631,7 @@ - - - +

z.B. Folding @@ -27392,9 +27390,7 @@ - - - +

...das ist nämlich potentiell verwirrend: der Außenbogen  bildet die Innenkontur der Klammer, weil der Schwung von der Klammer weg nach oben bzw. unten geht @@ -27953,9 +27949,7 @@ - - - +

Die ganze Doku, sowohl in GTK, alsauch die CSS Spec liest sich so, als wollte man sich vor einer Festlegung drücken. Möglicherweise hatte man Sorge, die dummen Leute würden zu einfache Schlußfolgerungen ziehen, und darob die Auflösung des Bildschirms übersehen — 96dpi ist ja nur ein Default, und ob 1pt= 1/72 inch wirklich gilt, darauf möchte sich niemand festnageln lasse, vermute ich (es hängt nämlich davon ab, daß Monitor und Grafikkarte diesen Wert richtig reporten) @@ -28747,9 +28741,7 @@ - - - +

wenn ich das Tupel als Referenz anliefere @@ -29107,9 +29099,7 @@ - - - +

anstatt, wie es die bisherige (naive) implementierung macht, @@ -29930,9 +29920,7 @@ - - - +

das Präludium gehört nicht zum Track, und für alle sonstigen Größenangaben gilt ein unmittelbarer Bezug auf die Canvas-Koordinaten; diese gelten lokal für den Canvas @@ -31773,9 +31761,7 @@ - - - +

nicht nur die Ruler, auch das Prelude selber ist ein solches gePinntes Element (selbst wenn es leer ist) @@ -33116,9 +33102,7 @@ - - - +

sollte theoretisch funktionieren.... @@ -33446,9 +33430,7 @@ - - - +

...trotzdem wurde die Idee eines generischen UI-Layout-Frameworks nach gründlicher Untersuchung aufgegeben; dies System der ViewHooks stiftet uns also "nur" ein Baumuster, und wir beschränken uns auf die bekannte kleine Zahl der konkreten Fälle, welche weitgehend im DisplayFrame gebündelt sind. Deshalb gibt es nun hilfsweise das Zugangs-Interface ViewHooks, von dem man alle relevanten, speziell getypten ViewHook, bzw. Canvas-Hook eben im aktuellen Display-Frame (relatives Koordinatensystem) beziehen kann. @@ -34379,9 +34361,7 @@ - - - +

kann sich selbst @@ -34880,9 +34860,7 @@ - - - +

Vorsicht Falle: es reicht nicht, nur die auf Pixel quantisierte Position zu speichern, denn diese wird bei geringem Zoom relativ ungenau. Es wäre leicht möglich, durch Heraus- und wieder Hereinscrollen die sichtbare Position eines Clip massiv zu verschieben. @@ -35162,9 +35140,7 @@ - - - +

Das ist eine Konsequenz aus dem Design des Diff-Framework; genauer, aus der konkreten Form, die die Implementierung des Diff-Framework bekommen hat: Und zwar, daß ein generischer Container gebunden wird. Das bedeutet, daß die Elemente im Container wie Werte behandelt werden. Und deshalb müssen sich Widgets selbständig vom Canvas abmelden. Die Alternative dazu wäre, daß der Parent den Diff interpretiert, und seine Kinder direkt manipuliert. Dann wären diese Kinder aber auch Widgets, und nicht nochmal indirekt als Presenter angebunden. Könnte man machen, habe ich aber ein mulmiges Gefühl. Da nehme ich dann doch lieber ein smart-Handle und einen Back-Pointer in Kauf. @@ -81559,7 +81535,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -88744,6 +88721,100 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +

+ ERR: tracking-heap-block-provider.cpp:129: ~BlockPool: Block actively in use while shutting down BufferProvider allocation pool. This might lead to Segfault and memory leaks. +

+ +
+
+ + + + +

+ wirkt alles noch latent unfertig hier.... +

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

+ auch Implementierung von all_buffers_released() fehlt +

+ + +
+ + + +

+ Glorreich — testgetriebene Entwicklung und dann den wichtigen zentralen Test >10 Jahre lang auskommentiert rumstehen lassen +

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

+ also muß ich im BlockPool alles als released markieren +

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

+ schließlich soll man ja sauber arbeiten +

+ +
+
+
+
+ + + +
@@ -88755,6 +88826,18 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + +
@@ -92291,17 +92374,38 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + - + + + + + + + + + + + + + + + + + + + + + @@ -92317,8 +92421,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
....das heißt, alle wichtigen Eigenschaften aus _ProcFun<FUN> müssen delegiert bereitgestellt werden...

- - +
@@ -92335,8 +92438,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
valide  ⟹  Funktor ist brauchbar

- - +
@@ -92351,6 +92453,13 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + +
@@ -92389,6 +92498,30 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + + + + + + + + + + + + + + + + + @@ -92785,6 +92918,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +
@@ -96798,6 +96935,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + +
@@ -98747,8 +98889,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -98964,8 +99107,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + @@ -98987,6 +99131,31 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + +

+ das Buffer-Protocol von 2012 +

+

+ betrachte ich als verbindlich +

+ +
+ + + + + + + +
+
@@ -139760,6 +139929,10 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + @@ -149998,13 +150171,27 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
- + - + + + + +

+ sieht aber soweit sauber aus... +

+

+ Wenngleich auch ziemlich elaboriert; all diese Tracking-Funktionalität war seinerzeit angelegt worden, aber nur oberflächlich getestet, weil der Render-Engine-Entwurf von 2012 letztlich steckengeblieben ist. Jetzt, 2024 beginne ich, den TrackingHeapBlockProvider zu für Tests zu nutzen, einfach weil er da ist — und stelle fest, daß einige Details unfertig und etwas unausgereift wirken.... +

+ +
+ + +