diff --git a/src/lib/split-splice.hpp b/src/lib/split-splice.hpp index 4cdedbddb..02dfccdc3 100644 --- a/src/lib/split-splice.hpp +++ b/src/lib/split-splice.hpp @@ -21,11 +21,11 @@ */ -/** @file splite-splice.cpp +/** @file splite-splice.hpp ** Generic algorithm to splice a new segment into a seamless segmentation of intervals. ** Here _"segmentation"_ denotes a partitioning of an ordered axis into a seamless sequence ** of intervals (here called "segment"). The axis is based on some _ordering type,_ like e.g. - ** int (natural numbers) or lib::time::Time values, and the axis is assumed cover a complete + ** `int` (natural numbers) or lib::time::Time values, and the axis is assumed to cover a complete ** domain. The intervals / segments are defined by start and end point, where the start point ** is inclusive, yet the end point is exclusive (the next ordered point after the interval). ** @@ -93,7 +93,7 @@ namespace lib { namespace error = lumiera::error; - namespace splitsplice {/// Implementation of [»SplitSplice« algorithm](\ref splite-splice.cpp) + namespace splitsplice {/// Implementation of [»SplitSplice« algorithm](\ref splite-splice.hpp) /** diff --git a/src/steam/fixture/segmentation.hpp b/src/steam/fixture/segmentation.hpp index 417dbeaae..de71102e5 100644 --- a/src/steam/fixture/segmentation.hpp +++ b/src/steam/fixture/segmentation.hpp @@ -78,7 +78,7 @@ namespace fixture { * * @todo 1/2012 Just a Placeholder. The real thing is not yet implemented. * @todo 4/2023 now about to bootstrap into the implementation structure step by step (WIP) - * @see http://lumiera.org/wiki/renderengine.html#Fixture + * @see https://lumiera.org/wiki/renderengine.html#Fixture */ class Segmentation : util::NonCopyable diff --git a/tests/core/steam/engine/job-planning-setup-test.cpp b/tests/core/steam/engine/job-planning-setup-test.cpp index 2246d10cc..88a4fb826 100644 --- a/tests/core/steam/engine/job-planning-setup-test.cpp +++ b/tests/core/steam/engine/job-planning-setup-test.cpp @@ -63,6 +63,7 @@ namespace test { * @todo WIP-WIP-WIP 4/2023 * * @see DispatcherInterface_test + * @see MockSupport_test * @see Dispatcher * @see CalcStream * @see RenderDriveS @@ -71,7 +72,7 @@ namespace test { { virtual void - run (Arg) + run (Arg) { demonstrateScaffolding(); UNIMPLEMENTED ("shape the interface of the job-planning pipeline"); @@ -88,33 +89,46 @@ namespace test { { Time nominalTime = lib::test::randTime(); int additionalKey = rand() % 5000; - Job mockJob = DummyJob::build (nominalTime, additionalKey); - CHECK (mockJob.getNominalTime() == nominalTime); - CHECK (not DummyJob::was_invoked (mockJob)); + Job mockJob = DummyJob::build (nominalTime, additionalKey); mockJob.triggerJob(); - CHECK ( DummyJob::was_invoked (mockJob)); + CHECK (DummyJob::was_invoked (mockJob)); CHECK (RealClock::wasRecently (DummyJob::invocationTime (mockJob))); CHECK (nominalTime == DummyJob::invocationNominalTime (mockJob) ); CHECK (additionalKey == DummyJob::invocationAdditionalKey(mockJob)); - Time prevInvocation = DummyJob::invocationTime (mockJob); - mockJob.triggerJob(); - CHECK (prevInvocation < DummyJob::invocationTime (mockJob)); // invoked again, recorded new invocation time - CHECK (nominalTime == DummyJob::invocationNominalTime (mockJob) ); // all other Job parameter recorded again unaltered - CHECK (additionalKey == DummyJob::invocationAdditionalKey(mockJob)); + // Build a simple Segment at [10s ... 20s[ + MockSegmentation mockSegs{MakeRec() + .attrib ("start", Time{0,10} // start time (inclusive) of the Segment at 10sec + ,"after", Time{0,20} // the Segment ends *before* 20sec + ,"mark", 123) // marker-ID 123 (can be verified from Job invocation) + .scope(MakeRec() // this JobTicket also defines a prerequisite ticket + .attrib("mark",555) // using a differen marker-ID 555 + .genNode() + ) + .genNode()}; + fixture::Segment const& seg = mockSegs[Time{0,15}]; // access anywhere 10s <= t < 20s + JobTicket const& ticket = seg.jobTicket(); // get the master-JobTicket from this segment + JobTicket const& prereq = *(ticket.getPrerequisites()); // pull a prerequisite JobTicket - MockJobTicket mockTick; - CHECK (mockTick.discoverPrerequisites().empty()); + FrameCoord coord; // Frame coordinates for invocation (placeholder) + Job jobP = prereq.createJobFor(coord); // create an instance of the prerequisites for this coordinates + Job jobM = ticket.createJobFor(coord); // ...and an instance of the master job for the same coordinates + CHECK (MockJobTicket::isAssociated (jobP, prereq)); + CHECK (MockJobTicket::isAssociated (jobM, ticket)); + CHECK (not MockJobTicket::isAssociated (jobP, ticket)); + CHECK (not MockJobTicket::isAssociated (jobM, prereq)); - MockSegmentation mockSeg; - UNIMPLEMENTED ("how to mock and fake"); - /////////////////////////////////////////////////////////////////////////////TODO: extract from DispatcherInterface_test - /////////////////////////////////////////////////////////////////////////////TODO: design a job-ticket-mock - /////////////////////////////////////////////////////////////////////////////TODO: create a scheme for mock-jobs + jobP.triggerJob(); + jobM.triggerJob(); + CHECK (123 == DummyJob::invocationAdditionalKey (jobM)); // verify each job was invoked and linked to the correct spec, + CHECK (555 == DummyJob::invocationAdditionalKey (jobP)); // indicating that in practice it will activate the proper render node + // + ////////////////////////////////////////////////////////////////////TODO: extract Dispatcher-Mock from DispatcherInterface_test } + /** @test use the Dispatcher interface (mocked) to generate a frame »beat« * @remark this is the foundation to generate top-level frame render jobs */ diff --git a/tests/core/steam/engine/mock-dispatcher.hpp b/tests/core/steam/engine/mock-dispatcher.hpp index 865ce04f9..5f322d0c9 100644 --- a/tests/core/steam/engine/mock-dispatcher.hpp +++ b/tests/core/steam/engine/mock-dispatcher.hpp @@ -1,5 +1,5 @@ /* - DISPATCHER-MOCK.hpp - test scaffolding to verify render job planning and dispatch + MOCK-DISPATCHER.hpp - test scaffolding to verify render job planning and dispatch Copyright (C) Lumiera.org 2023, Hermann Vosseler @@ -20,71 +20,59 @@ */ -/** @file testframe.hpp - ** Unit test helper to generate fake test data frames +/** @file mock-dispatcher.hpp + ** Mock data structures to support implementation testing of render job + ** planning and frame dispatch. Together with dummy-job.hpp, this provides + ** a specifically rigged test setup, allowing to investigate and verify + ** designated functionality in isolation, without backing by the actual + ** render engine implementation. + ** - the MockDispatcherTable emulates the frame dispatch from the Fixture + ** - MockSegmentation is a mocked variant of the »Segmentation« datastructure, + ** which forms the backbone of the Fixture and is the top-level attachment + ** point for the »low-level-Model« (the render nodes network) + ** - MockJobTicket is a builder / adapter on top of the actual steam::engine::JobTicket, + ** allowing to generate a complete rigged MockSegmentation setup from a generic + ** test specification written as nested lib::diff::GenNode elements. From this + ** setup, »mock jobs« can be generated, which use the DummyJob functor and + ** just record any invocation without performing actual work. + ** @remark in spring 2023, this setup was created as a means to define and + ** then build the actual implementation of frame dispatch and scheduling. + ** @see MockSupport_test */ -#ifndef STEAM_ENGINE_TEST_DISPATCHER_MOCK_H -#define STEAM_ENGINE_TEST_DISPATCHER_MOCK_H +#ifndef STEAM_ENGINE_TEST_MOCK_DISPATCHER_H +#define STEAM_ENGINE_TEST_MOCK_DISPATCHER_H -////#include "steam/engine/procnode.hpp" -//#include "steam/play/dummy-play-connection.hpp" +#include "lib/test/test-helper.hpp" #include "steam/fixture/segmentation.hpp" #include "steam/mobject/model-port.hpp" #include "steam/engine/dispatcher.hpp" #include "steam/engine/job-ticket.hpp" -//#include "steam/play/timings.hpp" -#include "lib/time/timevalue.hpp" -////#include "lib/time/timequant.hpp" -////#include "lib/format-cout.hpp" -#include "lib/diff/gen-node.hpp" -#include "lib/depend.hpp" -#include "lib/linked-elements.hpp" -#include "lib/itertools.hpp" -//#include "lib/iter-tree-explorer.hpp" -//#include "lib/util-coll.hpp" -#include "vault/real-clock.hpp" -#include "lib/test/test-helper.hpp" #include "vault/engine/job.h" #include "vault/engine/dummy-job.hpp" -#include "lib/util.hpp" +#include "vault/real-clock.hpp" +#include "lib/time/timevalue.hpp" +#include "lib/diff/gen-node.hpp" +#include "lib/linked-elements.hpp" +#include "lib/itertools.hpp" +#include "lib/depend.hpp" -//#include -//#include #include #include -//#include - -//using test::Test; -//using util::isnil; -//using util::last; -//using std::vector; -//using std::function; -//using std::rand; - -//#include -//#include namespace steam { namespace engine { namespace test { + using std::make_tuple; using lib::diff::GenNode; using lib::diff::MakeRec; -// using lib::time::FrameRate; -// using lib::time::Duration; -// using lib::time::Offset; -// using lib::time::TimeVar; using lib::time::TimeValue; using lib::time::Time; -// using mobject::ModelPort; -// using play::Timings; using lib::HashVal; - using std::make_tuple; -// using std::deque; ///////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1294 : organisation of namespaces / includes?? using fixture::Segmentation; @@ -138,10 +126,13 @@ namespace test { /// @deprecated this setup is confusing and dangerous (instance identity is ambiguous) lib::Depend mockDispatcher; +#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221 +#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221 + /* ===== specify a mock JobTicket setup for tests ===== */ template inline auto @@ -162,20 +153,24 @@ namespace test { }//(End)internal test helpers.... -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221 -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1221 + + /** - * Mock for... - * + * Mock setup for a JobTicket to generate DummyJob invocations. + * Implemented as subclass, it provides a specification DSL for tests, + * and is able to probe some otherwise opaque internals of JobTicket. + * Beyond that, MockJobTicket has the same storage size; and behaves + * like the regular JobTicket after construction -- but any Job + * created by JobTicket::createJobFor(FrameCoord) will be wired + * with the DummyJob functor and can thus be related back to + * the test specification setup. * @see JobPlanningSetup_test * @see DispatcherInterface_test - * */ class MockJobTicket : public JobTicket { - public: MockJobTicket() : JobTicket{defineSimpleSpec()} @@ -190,12 +185,34 @@ namespace test { : JobTicket{defineSpec (seed, std::forward (prereq))} { } + /* ===== Diagnostics ===== */ + bool verify_associated (Job const&) const; static bool isAssociated (Job const&, JobTicket const&); - private: }; + + /** + * Mock setup for a complete Segmentation to emulate the structure + * of the actual fixture, without the need of building a low-level Model. + * MockSegmentation instances can be instantiated directly within the + * test, by passing a test specification in »GenNode« notation to the + * constructor. This specification defines the segments to create + * and allows to associate a marker number, which can later be + * verified from the actual DummyJob invocation. + * - the ctor accepts a sequence of GenNode elements, + * each corresponding to a segment to created + * - optionally, attributes "start" and "after" can be defined + * to provide the lib::time::Time values of segment start/end + * - in addition, optionally a "mark" attribute can be defined; + * the given integer number will be "hidden" in the job instance + * hash, and can be [verified](\ref DummyJob::invocationAdditionalKey) + * - the _scope_ of each top-level GenNode may hold a sequence of + * nested nodes corresponding to _prerequisite_ JobTicket instances + * - these can in turn hold further nested prerequisites, and so on + * @see MockSetup_test::verify_MockSegmentation + */ class MockSegmentation : public Segmentation { @@ -222,7 +239,9 @@ namespace test { } } - private: + + private: /* ======== Implementation: build mock JobTickes from test specification ==== */ + HashVal buildSeed (GenNode const& spec) { @@ -236,7 +255,7 @@ namespace test { return lib::transformIterator (spec.getChildren() ,[this](GenNode const& childSpec) -> JobTicket& { - return buildTicketFromSpec (childSpec); + return buildTicketFromSpec (childSpec); }); } @@ -250,9 +269,10 @@ namespace test { + /** * verify the given job instance was actually generated from this JobTicket. - * @remark this test support function actually relies on some specific rigging, + * @remark this test support function relies on some specific rigging, * which typically is prepared by setup of a MockJobTicket. */ inline bool @@ -273,12 +293,11 @@ namespace test { */ inline bool MockJobTicket::isAssociated (Job const& job, JobTicket const& ticket) - { // should work always, since storage is the same + { // should work always, since storage is the same MockJobTicket const& backdoor = static_cast (ticket); return backdoor.verify_associated (job); } - }}} // namespace steam::engine::test -#endif /*STEAM_ENGINE_TEST_DISPATCHER_MOCK_H*/ +#endif /*STEAM_ENGINE_TEST_MOCK_DISPATCHER_H*/ diff --git a/tests/core/steam/engine/mock-support-test.cpp b/tests/core/steam/engine/mock-support-test.cpp index cff471cdb..368b36498 100644 --- a/tests/core/steam/engine/mock-support-test.cpp +++ b/tests/core/steam/engine/mock-support-test.cpp @@ -146,8 +146,14 @@ namespace test { } + /** @test document and verify usage of a complete mocked Segmentation * to back frame dispatch + * - default constructed: empty Segmentation + * - cover the whole axis with one segment + * - partition axis and verify the association of generated jobs + * - a fully defined segment within an otherwise empty axis + * - complex partitioning (using the »split-splice« mechanism */ void verify_MockSegmentation() @@ -155,6 +161,7 @@ namespace test { FrameCoord coord; Time someTime = lib::test::randTime(); coord.absoluteNominalTime = someTime; + // //-----------------------------------------------------------------/// Empty default Segmentation { MockSegmentation mockSeg; @@ -185,6 +192,7 @@ namespace test { { // Marker to verify the job calls back into the right segment int marker = rand() % 1000; + // // Build a Segmentation partitioned at 10s MockSegmentation mockSegs{MakeRec() .attrib ("start", Time{0,10} diff --git a/tests/core/vault/engine/dummy-job.cpp b/tests/core/vault/engine/dummy-job.cpp index 5b5cd2764..ffc13ccb8 100644 --- a/tests/core/vault/engine/dummy-job.cpp +++ b/tests/core/vault/engine/dummy-job.cpp @@ -21,7 +21,20 @@ * *****************************************************/ /** @file dummy-job.cpp - ** Implementation of a dummy render job for unit tests + ** Implementation of a dummy render job for unit tests. + ** Based on using a specifically rigged DummyClosure as JobFunctor, + ** where the actual Job invocation does nothing other than storing + ** the invocation mark and parameters into a invocationLog_ table. + ** Together with the likewise specifically rigged steam::engine::test::MockJobTicket, + ** the invocation hash can be marked, which allows to prove after the invocation + ** that a given Segment or JobTicket actually generated a specific Job, which was + ** then invoked with specific parameters. + ** + ** # Usage front-end + ** + ** The static functions in vault::engine::DummyJob allow to + ** - build such a mock job, possibly with random (or well defined) parameters + ** - when passing back this job instance, verify invocation and extract data */ @@ -58,9 +71,9 @@ namespace engine { /** * test dummy jobs are backed by this closure. * DummyJob invocations are recorded in a hashtable - * @note as of 9/2013, we use a very simplistic implementation, + * @note as of 5/2023, we use a simplistic map-based implementation, * causing a consecutive invocation of the same job instance - * to overwrite the previous log entry. + * with identical JobParameter to overwrite the previous log entry. */ class DummyClosure : public JobClosure @@ -96,7 +109,7 @@ namespace engine { /** * Generate a specifically marked invocationKey for use in unit-tests. * @remark in the actual implementation, this function generates a distinct - * base hash do tag specific processing provided by this JobFunctor; + * base hash to tag specific processing provided by this JobFunctor; * the seed usually factors in the media stream format; on invocation * the nominal frame time will additionally be hashed in. Yet for * unit testing, we typically use this dummy JobFunctor and it is @@ -164,7 +177,7 @@ namespace engine { - /** actual instance of the test dummy job operation */ + /** actual instance of the test dummy job functor */ DummyClosure dummyClosure; }// (End)Implementation details @@ -242,7 +255,6 @@ namespace engine { { return dummyClosure; } - }} // namespace vault::engine diff --git a/tests/core/vault/engine/dummy-job.hpp b/tests/core/vault/engine/dummy-job.hpp index 1d593b494..d12fb7c9a 100644 --- a/tests/core/vault/engine/dummy-job.hpp +++ b/tests/core/vault/engine/dummy-job.hpp @@ -21,7 +21,19 @@ */ /** @file dummy-job.hpp - ** Unit test helper to generate dummy render jobs + ** Unit test helper to generate dummy render jobs. + ** Render Jobs generated from this setup will not actually perform + ** any action, other than recording this invocation and the used + ** parameters into a map table managed behind the scenes. Using + ** the provided query function, it is possible to probe for such + ** an invocation and to extract the recorded parameter data. + ** + ** This setup is used both for stand-alone tests, which just require + ** "some job", but also as part of a complete hierarchy of mocked + ** data structures related to frame job dispatch and invocation + ** @see mock-dispatcher.hpp + ** @see MockSupport_test + ** */ @@ -58,6 +70,5 @@ namespace engine { static JobClosure& getFunctor(); }; - }} // namespace vault::engine #endif diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 43142f7bf..87f1d3236 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2530,10 +2530,10 @@ Additionally, they may be used for resource management purposes by embedding a r #* one OpenGL Dataframe could contain raw texture data (but I am lacking expertise for this topic) -
+
An entity within the RenderEngine, responsible for translating a logical [[calculation stream|CalcStream]] (corresponding to a PlayProcess) into a sequence of individual RenderJob entries, which can then be handed over to the [[Scheduler]]. Performing this operation involves a special application of [[time quantisation|TimeQuant]]: after establishing a suitable starting point, a typically contiguous series of frame numbers need to be generated, together with the time coordinates for each of those frames.
 
-The dispatcher works together with the job ticket(s) and the scheduler; actually these are the //core abstractions//&nbsp; the process of ''job planning'' relies on. While the actual scheduler implementation lives within the Vault, the job tickets and the dispatcher are located within the [[Segmentation]], which is the backbone of the [[low-level model|LowLevelModel]]. More specifically, the dispatcher interface is //implemented//&nbsp; by a set of &rarr; [[dispatcher tables|DispatcherTables]] within the segmentation.
+The dispatcher works together with the [[job ticket(s)|JobTicket]] and the scheduler; actually these are the //core abstractions//&nbsp; the process of ''job planning'' relies on. While the actual scheduler implementation lives within the Vault, the job tickets and the dispatcher are located within the [[Segmentation]], which is the backbone of the [[low-level model|LowLevelModel]]. More specifically, the dispatcher interface is //implemented//&nbsp; by a set of &rarr; [[dispatcher tables|DispatcherTables]] within the segmentation.
 
 {{red{stalled since 2014}}} -- development on this (important) topic has been postponed. Moreover, some rough edges remain within the Design &rarr; see [[some notes...|AboutMonads]]
 
@@ -6185,7 +6185,7 @@ This is the core service provided by the player subsystem. The purpose is to cre
 :any details of this processing remain opaque for the clients; even the player subsystem just accesses the EngineFaçade
 
-
+
//Integration effort to promote the development of rendering, playback and video display in the GUI//
 This IntegrationSlice was started in {{red{2023}}} as [[Ticket #1221|https://issues.lumiera.org/ticket/1221]] to coordinate the completion and integration of various implementation facilities, planned, drafted and built during the last years; this effort marks the return of development focus to the lower layers (after years of focussed UI development) and will implement the asynchronous and time-bound rendering coordinated by the [[Scheduler]] in the [[Vault|Vault-Layer]]
 
@@ -6200,6 +6200,14 @@ __12.Apr.23__: At start, this is a dauntingly complex effort, demanding to recon
 
 So the difficulties to understand my own (finished, working) code after several years compelled me to attempt a [[#1276|https://issues.lumiera.org/ticket/1276#comment:1]] refactoring of the FrameDispatcher, which I use as entrance point into the implementation of this //vertical slice//. This time I will approach the task as //on-demand processing pipeline// with //recursive expansion// -- attempting to segregate better what the monadic approach tended to interweave.
 
+__May.23__: taking a //prototyping approach// now, since further development was hampered by incomplete requirements analysis interlocked with incomplete implementation drafts. Based on a rough preconception (drafted &rarr; [[here|FrameDispatcher]] and in my //Mindmap//), a hierarchy of mocked data structures will be built up, which can then support erecting the remoulded internals of the dispatcher. After these are back to working state, the focus will move downwards, thereby step by step replacing the mocked structures by real structures -- only then will it be possibly to assess the new design. So presumably the next steps will be
+* ✔ augment the {{{DummyJob}}} to allow tracing Job invocations in tests
+* ✔ build a {{{MockJobTicket}}} on top, implemented as subclass of the actual JobTicket
+* ✔ build a {{{MockSegmentation}}} to hold onto ~JobTickets, which can be created as Mock
+* ✔define a simple specification language (based on the existing {{{GenNode}}}-DSL to define segments, tickets and prerequisite jobs
+* ✔ implement a »~Split-Splice« algorithm for &rarr; SegmentationChange, rigged accordingly to generate a mocked Segementation for now
+* 🗘 create a testbed to assemble a DispatcherPipeline step by step (&rarr; [[#920|https://issues.lumiera.org/ticket/920]] and [[#1275|https://issues.lumiera.org/ticket/1275|]])
+
 !Decisions
 ;Scheduler
 :is understood as a high-level Service, not a bare bone implementation mechanism
@@ -7141,7 +7149,7 @@ The Fixture is mostly comprised of the Segementation datastructure, but some oth
 Largely the storage of the render nodes network is hooked up behind the Fixture &rarr; [[storage considerations|FixtureStorage]]
 
-
+
At the end of the build process, the existing [[Segmentation]] possibly needs to be changed, extended or adapted.
 This change must be performed as a //transactional switch,// since render or playback processes might be performed concurrently. All Fixture and low-level-Model datastructures are //immutable// -- thus for any changes, suitably adapted structures will be built as a replacement.
 
@@ -7149,7 +7157,6 @@ This change must be performed as a //transactional switch,// since render or pla
 This is an implementation level operation, which analyses the existing Segmentation and determines the changes necessary to introduce a new or altered Segment. This operation has to retain the Segmentation ''Invariant'': it is a seamless sequence of Time intervals covering the complete time axis.
 
 !!!Structure of the split-splice operation
-{{red{1.5.2023 : Analysis and implementation draft}}}
 ;Invariant
 :complete and valid [[Segmentation]] always retained
 :* seamless coverage the complete time axis [-∞ .. +∞]
@@ -7219,6 +7226,9 @@ This is an implementation level operation, which analyses the existing Segmentat
 
 !!!Implementation techique
 The split-splice operation is performed always for a single segment in the context of an existing segmentation; the covered range can be defined explicitly, or by partial spec. For each application of this algorithm, an instance of a //working context// is created (on stack) and initialised by scanning the existing segmentation to establish the insert point. The four stages are then performed on this working data, thereby determining the handling cases -- and in the last stage, new elements are inserted and existing elements are deleted (assuming immutable segment data, any changes and adaptations are done by inserting a modified clone copy).
+
+!!!Generalisation
+The first implementation drafts furthered the observation that this decision scheme is actually not dependent on the specifics of the segmentation data structure; it can be generalised rather easily to to work on //any ordered discrete axis// and to handle generic intervals covering this axis in part or complete. The implementation can thus be turned into a ''template'', which is then instantiated with a ''binding'' to a concrete data structure, providing a few generic operation as λ-Functions. This allows to use a dedicated test binding for intervals over natural numbers -- used for exhaustive test coverage by systematically probing all logically possible invocation situations. This helped to spot some obscured bugs and fill-in some details of the implementation, notably the behaviour on incomplete specification of the new interval to splice in.
 
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index acf220d70..16407fe60 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -54456,6 +54456,26 @@ + + + + + + + + + + + + +

+ Ein Pointer wird in diesem Kontext wie ein einfacher primitiver value behandelt, d.h. value_type ≡ der Pointer selber, reference  ≡ eine Referenz auf den Pointer, pointer ≡ ein Pointer auf den Pointer. Und: aus einem Pointer werden niemals nested type bindings abgegriffen. +

+ +
+
+ +
@@ -54550,7 +54570,7 @@ - + @@ -68630,7 +68650,7 @@ - + @@ -69412,18 +69432,33 @@ - +

- verwendet noch den pre-C++11-Stil mit explizit ausgewalzten Template-Spezialisierungen für 1...5 Argumente + verwendete noch den pre-C++11-Stil mit explizit ausgewalzten Template-Spezialisierungen für 1...5 Argumente +

+

+ +

+

+ geändert mit +

+
+ +

+commit 856d8a3b519e4fc99e7b6749fbed67df33128741
+Author: Ichthyostega <prg@ichthyostega.de>
+Date:   Thu Apr 20 18:53:17 2023 +0200
+
+    Library: allow to reverse intrusive single linked list

- +
@@ -69434,6 +69469,7 @@ + @@ -69458,6 +69494,13 @@ + + + + + + + @@ -69519,8 +69562,13 @@
+ +
+
+ + @@ -69588,6 +69636,7 @@ + @@ -69597,7 +69646,7 @@ - + @@ -69725,7 +69774,7 @@ - + @@ -69735,18 +69784,21 @@ - - - - - + + + + + + + + - - + + - - + + @@ -69772,8 +69824,8 @@ - - + + @@ -69800,9 +69852,10 @@ - - - + + + + @@ -69816,8 +69869,8 @@ - - + + @@ -69950,7 +70003,7 @@ - + @@ -69993,6 +70046,7 @@ + @@ -71534,6 +71588,7 @@ + @@ -71765,8 +71820,7 @@ list::emplace_back  funktioniert

- - +
@@ -71931,7 +71985,7 @@
- + @@ -71943,16 +71997,37 @@ - + + - + + - + + - - + + + + + + + + + + + + + + + + + + + + @@ -71963,11 +72038,26 @@

+ + + - + + + + + + + + + + + + + @@ -72551,12 +72641,16 @@ + +
- + + - - + + + @@ -72585,15 +72679,19 @@ - - - + + + + + + - - + + + @@ -72604,9 +72702,9 @@ - - - + + + @@ -72657,13 +72755,36 @@ - + + + + + + +

+ Spezifikation: JobTicket erstellen +

+ +
+ + - - + + + + + + + + + + + - + + + @@ -72788,7 +72909,7 @@ - + @@ -72816,33 +72937,71 @@ - - + + + + + + - - - - + + + + + + +

+ über die interne Provision-Datastruktur (LinkedElements) +

+ +
+
+
+ + + +
+ + + + + + + + + + + + +
+ + + + + + + - - - - + + - - + + - - + + + + + @@ -72850,9 +73009,9 @@ - - + + @@ -72873,9 +73032,13 @@ - + - + + + + + @@ -72990,6 +73153,15 @@ + + + + + + + + + @@ -73010,6 +73182,7 @@ + @@ -73224,8 +73397,8 @@ - - + + @@ -73586,7 +73759,8 @@ - + +