From 42ac55ea7b9864f5942491e8e72a5adafd8a7493 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 13 Jul 2023 14:57:28 +0200 Subject: [PATCH] Block-Flow: promote IterableDecorator While at first sight just a superficial variation of the existing IterStateWrapper, it became clear with the evolution of the IterExplorer framework that this setup represents a distinct concept, and especially lends itself for complex and cohesive collaboration in a layered pipeline. Which may, or may not be a good idea, depending on the circumstances. Now, for the implementation of the scheduler memory allocation scheme, another twist is added to the picture: we can not effort the sanity checks on each access, even more so when layering / adapting iterators, where it is essential that the optimiser can remove all unnecessary warts. --- src/lib/iter-adapter.hpp | 181 ++++++++++++++++++++++++++++------ src/lib/iter-explorer.hpp | 108 +------------------- src/vault/gear/block-flow.hpp | 6 +- wiki/thinkPad.ichthyo.mm | 181 ++++++++++++++++++++++++++++++++-- 4 files changed, 328 insertions(+), 148 deletions(-) diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index a0ce46003..97a7d1256 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -460,39 +460,156 @@ namespace lib { */ template class IterStateCore - : public IT + : public IT + { + static_assert (lib::meta::can_IterForEach::value + ,"Lumiera Iterator required as source"); + protected: + IT& + srcIter() const + { + return unConst(*this); + } + + public: + using IT::IT; + + /* === state protocol API for IterStateWrapper === */ + bool + checkPoint() const + { + return bool(srcIter()); + } + + typename IT::reference + yield() const + { + return *srcIter(); + } + + void + iterNext() + { + ++ srcIter(); + } + }; + + + + + /** + * Decorator-Adapter to make a »state core« iterable as Lumiera Forward Iterator. + * This is a fundamental (and low-level) building block and works essentially the + * same as IterStateWrapper — with the significant difference however that the + * _Core is mixed in by inheritance_ and thus its full interface remains publicly + * accessible. Another notable difference is that this adapter deliberately + * *performs no sanity-checks*. This can be dangerous, but allows to use this + * setup even in performance critical code. + * @warning be sure to understand the consequences of using ´core.yield()´ without + * checks; it might be a good idea to build safety checks into the Core + * API functions instead. + * @tparam T nominal result type (maybe const, but without reference). + * The resulting iterator will yield a reference to this type T + * @tparam COR type of the »state core«. The resulting iterator will _mix-in_ + * this type, and thus inherit properties like copy, move, VTable, POD. + * The COR must implement the following _iteration control API:_ + * -# `checkPoint` establishes if the given state element represents a valid state + * -# ´iterNext` evolves this state by one step (sideeffect) + * -# `yield` realises the given state, exposing a result of type `T&` + */ + template + class IterableDecorator + : public COR + { + COR & _core() { return static_cast (*this); } + COR const& _core() const { return static_cast (*this); } + + protected: + void + __throw_if_empty() const + { + if (not isValid()) + _throwIterExhausted(); + } + + public: + typedef T* pointer; + typedef T& reference; + typedef T value_type; + + /** by default, pass anything down for initialisation of the core. + * @note especially this allows move-initialisation from an existing core. + * @remarks to prevent this rule from "eating" the standard copy operations, + * and the no-op default ctor, we need to declare them explicitly below. + */ + template + IterableDecorator (ARGS&& ...init) + : COR(std::forward(init)...) + { } + + IterableDecorator() =default; + IterableDecorator (IterableDecorator&&) =default; + IterableDecorator (IterableDecorator const&) =default; + IterableDecorator& operator= (IterableDecorator&&) =default; + IterableDecorator& operator= (IterableDecorator const&) =default; + + + /* === lumiera forward iterator concept === */ + + explicit operator bool() const { return isValid(); } + + reference + operator*() const + { + return _core().yield(); // core interface: yield + } + + pointer + operator->() const + { + return & _core().yield(); // core interface: yield + } + + IterableDecorator& + operator++() + { + _core().iterNext(); // core interface: iterNext + return *this; + } + + bool + isValid () const + { + return _core().checkPoint(); // core interface: checkPoint + } + + bool + empty () const + { + return not isValid(); + } + + + + ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (IterableDecorator); + + + /// Supporting equality comparisons of equivalent iterators (equivalent state core)... + template + friend bool + operator== (IterableDecorator const& il, IterableDecorator const& ir) { - static_assert (lib::meta::can_IterForEach::value - ,"Lumiera Iterator required as source"); - protected: - IT& - srcIter() const - { - return unConst(*this); - } - - public: - using IT::IT; - - /* === state protocol API for IterStateWrapper === */ - bool - checkPoint() const - { - return bool(srcIter()); - } - - typename IT::reference - yield() const - { - return *srcIter(); - } - - void - iterNext() - { - ++ srcIter(); - } - }; + return (il.empty() and ir.empty()) + or (il.isValid() and ir.isValid() and il._core() == ir._core()); + } + + template + friend bool + operator!= (IterableDecorator const& il, IterableDecorator const& ir) + { + return not (il == ir); + } + }; diff --git a/src/lib/iter-explorer.hpp b/src/lib/iter-explorer.hpp index 8a6d10182..20a59bf51 100644 --- a/src/lib/iter-explorer.hpp +++ b/src/lib/iter-explorer.hpp @@ -175,112 +175,6 @@ namespace lib { }; - /** - * Decorate a state or logic core to treat it as Lumiera Forward Iterator. - * This Adapter does essentially the same as \ref IterStateWrapper, but here - * the state core is not encapsulated opaque, but rather inherited, and thus - * the full interface of the core remains publicly accessible. - */ - template - class IterableDecorator - : public COR - { - COR & _core() { return static_cast (*this); } - COR const& _core() const { return static_cast (*this); } - - protected: - void - __throw_if_empty() const - { - if (not isValid()) - throw lumiera::error::Invalid ("Can't iterate further", - lumiera::error::LUMIERA_ERROR_ITER_EXHAUST); - } - - - public: - typedef T* pointer; - typedef T& reference; - typedef T value_type; - - /** by default, pass anything down for initialisation of the core. - * @note especially this allows move-initialisation from an existing core. - * @remarks to prevent this rule from "eating" the standard copy operations, - * and the no-op default ctor, we need to declare them explicitly below. - */ - template - IterableDecorator (ARGS&& ...init) - : COR(std::forward(init)...) - { } - - IterableDecorator() =default; - IterableDecorator (IterableDecorator&&) =default; - IterableDecorator (IterableDecorator const&) =default; - IterableDecorator& operator= (IterableDecorator&&) =default; - IterableDecorator& operator= (IterableDecorator const&) =default; - - - /* === lumiera forward iterator concept === */ - - explicit operator bool() const { return isValid(); } - - reference - operator*() const - { - __throw_if_empty(); - return _core().yield (); // core interface: yield - } - - pointer - operator->() const - { - __throw_if_empty(); - return & _core().yield(); // core interface: yield - } - - IterableDecorator& - operator++() - { - __throw_if_empty(); - _core().iterNext(); // core interface: iterNext - return *this; - } - - bool - isValid () const - { - return _core().checkPoint(); // core interface: checkPoint - } - - bool - empty () const - { - return not isValid(); - } - - - - ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (IterableDecorator); - - - /// Supporting equality comparisons of equivalent iterators (same state core)... - template - friend bool - operator== (IterableDecorator const& il, IterableDecorator const& ir) - { - return (il.empty() and ir.empty()) - or (il.isValid() and ir.isValid() and il._core() == ir._core()); - } - - template - friend bool - operator!= (IterableDecorator const& il, IterableDecorator const& ir) - { - return not (il == ir); - } - }; - - /** * Adapt an IterSource to make it iterable. As such, lib::IterSource is meant * to be iterable, while only exposing a conventional VTable-based _iteration interface_. @@ -403,7 +297,7 @@ namespace lib { struct _DecoratorTraits>> { using SrcVal = typename CoreYield::value_type; - using SrcIter = iter_explorer::IterableDecorator; + using SrcIter = lib::IterableDecorator; }; template diff --git a/src/vault/gear/block-flow.hpp b/src/vault/gear/block-flow.hpp index 00d13f594..6af893b81 100644 --- a/src/vault/gear/block-flow.hpp +++ b/src/vault/gear/block-flow.hpp @@ -249,7 +249,7 @@ namespace gear { return AllocatorHandle{alloc_.begin()}; } else - { + {//find out how the given time relates to existing Epochs UNIMPLEMENTED ("search through existing Epochs to locate the latest one to support given deadline"); } } @@ -257,7 +257,9 @@ namespace gear { void discardBefore (Time deadline) { - UNIMPLEMENTED ("traverse oldest Epochs and discard obsoleted"); + if (isnil (alloc_) + or asEpoch(alloc_.first()).gate().deadline() > deadline) + return; } private: diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index c51a7d6b3..8914df022 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -54483,13 +54483,34 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -54522,6 +54543,53 @@ + + + + + + + + + + + + + + + + + + + + +

+ Das Konzept des State-Core-Adapters hat sich im Lauf der Jahre herausgebildet, und wird mehr und mehr zu einer fundamentalen Struktur des Iteratoren-Framworks (in dem Maß, wie aus ad-hoc - Adaptern ein ganzes Framework entstanden ist). Im zweiten Anlauf für den Iter(Tree)Explorer habe ich das bereits erkannt, und die gesamte Pipeline darauf aufgebaut; allerdings zeigte sich hier, daß genau die Entscheidung, die »StateCore« als opaque zu betrachten, im größeren Kontext nicht trägt. Daher habe ich hier bewußt die Core als Basisklasse eingemischt; daraus ist der definierende Wesenszug des IterExplorers entstanden, der aber auch gleichzeitig seine größte Gefahr und Schwäche ist: das komplexe hoch-kohäsive Layering. Und nun stoße ich beim Aufbauen der Allokator-Hierarchie für den Scheduler enteut auf eine ähnlich gelagerte Situation, kann aber (da es sich um high-Performance-Code handelt), definitiv nicht den IterExplorer einsetzen. Dies bewegt mich zu dem Schritt, den IterableDecorator als ein eigenständiges Konzept zu etablieren. +

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

damit wäre dieser Adapter ein »Iterator-Implementierungs-Atom«

+ +
+ +
+
+
+
@@ -78770,7 +78838,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79744,6 +79812,105 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + + + + + + +

+ Grundproplem: downcast  + Extent +   ⟼  + Epoch +

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

+ es ist alles Inline und in einer einzigen Klassenhierarchie, + und die Iteratoren sind hier komplett PODs +

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

+ ...das war eine Design-Entscheidung, die im allgemeinen richtig ist (es lohnt sich nicht, auf bound-checking zu verzichten). Aber hier sind wir in einer high-Performance-Zone, und es wäre gefährlich, sich nur darauf zu verlassen, daß der Compiler das per globaler Optimierung noch repariert.... +

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