From c29c10fd629609e4063aaa632eb90afb8c290eaa Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 26 Oct 2024 03:03:11 +0200 Subject: [PATCH] Invocation: runtime error checks for auto-wiring Since it would in fact be possible to access and write beyond the configured storage, simply by using the builder API without considering consistency, it seems advisable to use explicit runtime checks here, instead of only assertions, and to throw an exception when violating bounds. Moreover, unsuccessfully attempted to better arrange the functionality between PortBuilder and WeavingBuilder; seemingly we have an rather tight coupling here, and also the expectations regarding the processing function seem to be too tight (but that's the reason why it's an prototype...) --- src/steam/engine/weaving-pattern-builder.hpp | 29 +++++- .../core/steam/engine/test-rand-ontology.hpp | 3 +- wiki/thinkPad.ichthyo.mm | 91 +++++++++++-------- 3 files changed, 77 insertions(+), 46 deletions(-) diff --git a/src/steam/engine/weaving-pattern-builder.hpp b/src/steam/engine/weaving-pattern-builder.hpp index c912eecc4..3566ea323 100644 --- a/src/steam/engine/weaving-pattern-builder.hpp +++ b/src/steam/engine/weaving-pattern-builder.hpp @@ -100,6 +100,7 @@ #define STEAM_ENGINE_WEAVING_PATTERN_BUILDER_H //#include "steam/common.hpp" +#include "lib/error.hpp" //#include "steam/engine/channel-descriptor.hpp" //#include "vault/gear/job.h" #include "lib/several-builder.hpp" @@ -107,7 +108,8 @@ #include "steam/engine/engine-ctx.hpp" #include "steam/engine/buffer-provider.hpp" #include "steam/engine/buffhandle-attach.hpp" /////////////////OOO why do we need to include this? we need the accessAs() template function -#include "lib/test/test-helper.hpp" +#include "lib/test/test-helper.hpp" ////////////////////////////OOO TODO added for test +#include "lib/format-string.hpp" //#include "lib/util-foreach.hpp" //#include "lib/iter-adapter.hpp" //#include "lib/meta/function.hpp" @@ -122,10 +124,12 @@ namespace steam { namespace engine { + namespace err = lumiera::error; using std::forward; using lib::Several; using lib::Depend; + using util::_Fmt; using util::max; @@ -357,6 +361,9 @@ namespace engine { using FunSpec = _ProcFun; using TurnoutWeaving = Turnout>; static constexpr SizMark sizMark{}; + static constexpr uint FAN_I = FunSpec::FAN_I; + static constexpr uint FAN_O = FunSpec::FAN_O; + using TypeMarker = std::function; using ProviderRef = std::reference_wrapper; @@ -380,9 +387,13 @@ namespace engine { WeavingBuilder&& attachToLeadPort (ProcNode& lead, uint portNr) { + if (leadPorts.size() >= FAN_I) + throw err::Logic{_Fmt{"Builder: attempt to add further input, " + "but all %d »input slots« of the processing function are already connected."} + % FAN_I + }; PortRef portRef{lead.getPort (portNr)}; leadPorts.append (portRef); - ENSURE (leadPorts.size() <= N); /////////////////////////////////////OOO must throw exception here, since bounds can be violated by API usage return move(*this); } @@ -390,6 +401,11 @@ namespace engine { WeavingBuilder&& appendBufferTypes (uint cnt) { + if (buffTypes.size()+cnt > FAN_O) + throw err::Logic{_Fmt{"Builder: attempt add %d further output buffers, " + "while %d of %d possible outputs are already connected."} + % cnt % buffTypes.size() % FAN_O + }; while (cnt--) buffTypes.emplace_back([](BufferProvider& provider) { return provider.getDescriptor(); }); @@ -400,7 +416,6 @@ namespace engine { WeavingBuilder&& fillRemainingBufferTypes() { - auto constexpr FAN_O = FunSpec::FAN_O; using BuffO = typename FunSpec::BuffO; uint cnt = FAN_O - buffTypes.size(); return appendBufferTypes(cnt); @@ -409,10 +424,14 @@ namespace engine { WeavingBuilder&& connectRemainingInputs (DataBuilder& knownLeads, uint defaultPort) { - auto constexpr FAN_I = FunSpec::FAN_I; REQUIRE (leadPorts.size() <= FAN_I); uint cnt = FAN_I - leadPorts.size(); - REQUIRE (leadPorts.size() + cnt <= knownLeads.size()); ////////////////////OOO determine if this should also be rather an exception? + if (FAN_I > knownLeads.size()) + throw err::Logic{_Fmt{"Builder: attempt to auto-connect %d further »input slots«, " + "but this ProcNode has only %d predecessor nodes, while the " + "given processing function expects %d inputs."} + % cnt % knownLeads.size() % FAN_I + }; while (cnt--) attachToLeadPort (knownLeads[leadPorts.size()], defaultPort); return move(*this); diff --git a/tests/core/steam/engine/test-rand-ontology.hpp b/tests/core/steam/engine/test-rand-ontology.hpp index 10a57dbeb..405740b50 100644 --- a/tests/core/steam/engine/test-rand-ontology.hpp +++ b/tests/core/steam/engine/test-rand-ontology.hpp @@ -40,11 +40,12 @@ namespace test { /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1367 : Dummy / Placeholder + using NoArg = std::array; using SoloArg = std::array; /** @todo a placeholder operation to wire a prototypical render node */ inline void - dummyOp (SoloArg in, SoloArg out) + dummyOp (NoArg in, SoloArg out) { UNIMPLEMENTED ("a sincerely nonsensical operation"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 23a99ed8b..30cad4cef 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -13196,9 +13196,7 @@ - - - +

Regel-Parametrisierung @@ -13604,9 +13602,7 @@ - - - +

für LocationQuery @@ -14302,9 +14298,7 @@ - - - +

um eine Position zu kennzeichnen @@ -15620,9 +15614,7 @@ - - - +

....anders als im Diff-Framework @@ -18060,9 +18052,7 @@ - - - +

...denn GTK geht von einer fixen Mindestgröße aus, einem Allocation-Request und dann einer Platzzuteilung @@ -48782,9 +48772,7 @@ - - - +

  • @@ -49421,9 +49409,7 @@ - - - +

    Auf theoretischer Ebene handel es sich um eine (nicht notwendigerweise deterministische) State-Machine. Allerdings ist diese sehr breit, und daher nicht sinnvoll direkt zu konstruieren. Wohingegen eine Tabellen-Implementierung aus Regeln dynamisch populiert werden kann @@ -49794,9 +49780,7 @@ - - - +

    Kennzeichen ist die EntryID des zugehörigen Elements @@ -49903,9 +49887,7 @@ - - - +

    ich will nicht damit anfangen, daß man einen Zeiger umsetzen kann.... @@ -49977,9 +49959,7 @@ - - - +

    Beispiel: @@ -50124,9 +50104,7 @@ - - - +

    konzeptionell: fertig @@ -90405,8 +90383,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - + + @@ -90415,7 +90393,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - + @@ -90423,15 +90401,48 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    PRECONDITION: weaving-pattern-builder.hpp:415: thread_1: connectRemainingInputs: (leadPorts.size() + cnt <= knownLeads.size())

    +
    + + + + + +

    + wir definieren eine Quell-Node ohne Vorgänger, aber binden eine Funktion mit einem Input-Slot +

    +
    - +
    + + + + + +

    + ...doch dazu ist das ganze Introspection-Schema für die processing-Function (im Moment) viel zu starr +

    + + +
    + +
    - + + + + + + + + + + +
    @@ -90440,8 +90451,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
    - - + +