Segmentation: consider preliminary data structure

...and consider how that can be extended later into the full
structure, which has to support a transactional switch
This commit is contained in:
Fischlurch 2023-04-27 19:38:37 +02:00
parent d58174db4d
commit d73b316ead
10 changed files with 280 additions and 16 deletions

View file

@ -296,6 +296,7 @@ namespace time {
return reinterpret_cast<Duration const&> (maxDelta);
}();
const TimeSpan TimeSpan::ALL {Time::MIN, Duration::MAX};
}} // namespace lib::Time

View file

@ -600,6 +600,8 @@ namespace time {
TimeSpan conform() const; ///< @return a copy conformed to time domain limits
static const TimeSpan ALL;
Duration&
duration()
{

View file

@ -77,11 +77,11 @@ namespace fixture {
: util::NonCopyable
{
protected:
/////////////////////////////////////////////////TODO: placeholder code
///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #725 : placeholder code
list<ExplicitPlacement> content_;
unique_ptr<Segmentation> partitioning_;
/////////////////////////////////////////////////TICKET #573 who creates the fixture?
///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #573 who creates the fixture?
public:
list<ExplicitPlacement> & getPlaylistForRender () ;

View file

@ -43,31 +43,38 @@ namespace steam {
namespace fixture {
using mobject::ExplicitPlacement;
using lib::time::TimeSpan;
/**
* For the purpose of building and rendering, the fixture (for each timeline)
* is partitioned such that each segment is <i>structurally constant</i>.
* For each segment there is a RenderGraph (unit of the render engine) which
* is able to render all ExitNodes for this segment.
* is partitioned such that each segment is _structurally constant._
* For each segment there is a RenderGraph (unit of the render engine)
* which is able to render all ExitNodes for this segment.
*
* @ingroup fixture
* @todo 1/2012 Just a Placeholder. The real thing is not yet implemented.
* @todo WIP-WIP as of 4/2023 -- about to pull up the engine backbone
* @see http://lumiera.org/wiki/renderengine.html#Fixture
*/
class Segment
{
protected:
typedef lib::time::TimeSpan Span;
/** begin of this timeline segment. */
Span span_;
TimeSpan span_;
///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #725 : placeholder code
/** relevant MObjects comprising this segment. */
list<ExplicitPlacement> elements;
// TODO: actually necessary??
// TODO: ownership??
///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #725 : placeholder code
public:
Segment (TimeSpan covered =TimeSpan::ALL)
: span_{covered}
{ }
/////////////////////////////////////////////////TODO: placeholder code
// default copy acceptable
};

View file

@ -48,6 +48,7 @@
#include "steam/fixture/segment.hpp"
#include "lib/nocopy.hpp"
#include <list>
@ -72,14 +73,28 @@ namespace fixture {
* @see http://lumiera.org/wiki/renderengine.html#Fixture
*/
class Segmentation
: util::NonCopyable
{
/////////////////////////////////////////////////TODO: placeholder code
///////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1243 : preliminary implementation
/** segments of the engine in ordered sequence. */
list<Segment> segments_;
public:
virtual ~Segmentation(); ///< this is an interface
protected:
Segmentation() ///< there is always a single cover-all Segment initially
: segments_{1}
{ }
public:
size_t
size() const
{
return segments_.size();
}
};

View file

@ -49,6 +49,16 @@ return: 0
END
PLANNED "Setup for render job planning" JobPlanningSetup_test <<END
return: 0
END
PLANNED "Mock support for render job planning" MockSupport_test <<END
return: 0
END
PLANNED "Proc Node basics" NodeBasic_test <<END
END

View file

@ -182,11 +182,11 @@ namespace test {
public:
MockSegmentation()
: MockSegmentation{MakeRec().genNode()}
: tickets_{}
{ }
MockSegmentation (std::initializer_list<GenNode> specs)
: tickets_{}
: MockSegmentation{}
{
UNIMPLEMENTED ("populate mock sequence structure");
}

View file

@ -0,0 +1,139 @@
/*
MockSupport(Test) - verify test support for fixture and job dispatch
Copyright (C) Lumiera.org
2023, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file mock-support-test.cpp
** unit test \ref MockSupport_test
*/
#include "lib/test/run.hpp"
#include "lib/error.hpp"
#include "steam/engine/mock-dispatcher.hpp"
#include "vault/engine/dummy-job.hpp"
#include "lib/format-cout.hpp"///////////////////////TODO
//#include "steam/engine/job-planning.hpp"
//#include <ctime>
using test::Test;
//using std::rand;
namespace steam {
namespace engine{
namespace test {
using vault::engine::DummyJob;
namespace { // test fixture...
} // (End) test fixture
/**********************************************************************//**
* @test validate test support for render job planning and dispatch.
* - creating and invoking mock render jobs
* - a mocked JobTicket, generating mock render jobs
* - configurable test setup for a mocked Segmentation datastructure
*
* @todo WIP-WIP-WIP 4/2023
*
* @see JobPlanningSetup_test
* @see Dispatcher
* @see vault::engine::Job
* @see steam::fixture::Segmentation
*/
class MockSupport_test : public Test
{
virtual void
run (Arg)
{
simpleUsage();
verify_MockJob();
verify_MockJobTicket();
verify_MockSegmentation();
}
/** @test simple usage example of the test helpers */
void
simpleUsage()
{
TODO ("simple usage example");
}
/** @test document and verify usage of a mock render job */
void
verify_MockJob()
{
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));
mockJob.triggerJob();
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));
}
/** @test document and verify usage of a mock JobTicket for frame dispatch */
void
verify_MockJobTicket()
{
MockJobTicket mockTick;
CHECK (mockTick.discoverPrerequisites().empty());
TODO ("cover details of MockJobTicket");
}
/** @test document and verify usage of a complete mocked Segmentation to back frame dispatch */
void
verify_MockSegmentation()
{
MockSegmentation mockSeg;
CHECK (1 == mockSeg.size());
TODO ("cover details of MockSegmentation");
}
};
/** Register this test class... */
LAUNCHER (MockSupport_test, "unit engine");
}}} // namespace steam::engine::test

View file

@ -2303,7 +2303,7 @@ Any feed corresponds to a specific ModelPort, which in turn typically correspond
When starting playback or render, a play process (with a PlayController front-end for client code) is established to coordinate the processing. This ongoing data production might encompass multiple media streams, i.e. multiple feeds pulled from several model ports and delivered into several [[output slots|OutputSlot]]. Each feed in turn might carry structured MultichannelMedia, and is thus further structured into individual [[streams of calculation|CalcStream]]. Since the latter are //stateless descriptors,// while the player and play process obviously is stateful, it's the feed's role to mediate between a state-based (procedural) and a stateless (functional and parallelised) organisation model -- ensuring a seamless data feed even during modification of the playback parameters.
</pre>
</div>
<div title="Fixture" modifier="Ichthyostega" created="200706220324" modified="201201281945" tags="def spec Builder Model">
<div title="Fixture" modifier="Ichthyostega" created="200706220324" modified="202304271631" tags="def spec Builder Model" changecount="2">
<pre>a specially configured view -- joining together high-level and low-level model.
The Fixture acts as //isolation layer// between the two models, and as //backbone to attach the render nodes.//
* all MObjects have their position, length and configuration set up ready for rendering.
@ -2335,9 +2335,13 @@ The fixture is like a grid, where one dimension is given by the [[model ports|Mo
;Exit Nodes
:Each segment holds an ExitNode for each relevant ModelPort of the corresponding timeline.
:Thus the exit nodes are keyed by ~Pipe-ID as well (and consequently have a distinct [[stream type|StreamType]]) -- each model port coresponds to {{{&lt;number_of_segments&gt;}}} separate exit nodes, but of course an exit node may be //mute//&amp;nbsp; in some segmehts.
!!!Dependencies
At architecture level, the Fixture is seen as //interface// between Steam-Layer and Vault-Layer.
This raises the question: {{red{(WIP 4/23) where is the fixture data structure defined, in terms of code dependencies?}}}
</pre>
</div>
<div title="FixtureDatastructure" modifier="Ichthyostega" created="201012162304" modified="201112171816" tags="spec Builder">
<div title="FixtureDatastructure" modifier="Ichthyostega" created="201012162304" modified="202304271626" tags="spec Builder" changecount="4">
<pre>Generally speaking, the datastructure to implement the ''Fixture'' (&amp;rarr; see a more general description [[here|Fixture]]) is comprised of a ModelPortRegistry and a set of [[segmentations|Segmentation]] per Timeline.
This page focusses on the actual data structure and usage details on that level. See also &amp;rarr; [[storage|FixtureStorage]] considerations.
@ -2345,6 +2349,7 @@ This page focusses on the actual data structure and usage details on that level.
A key point to note is the fact that the fixture is frequently [[re-built|BuildFixture]] by the [[Builder]], while render processes may be going on in parallel. Thus, when a build process is finished, a transactional ''commit'' happens to ''hot swap'' the new parts of the model. This is complemented by a clean-up of tainted render processes; finally, storage can be reclaimed.
To support this usage pattern, the Fixture implementation makes use of the [[PImpl pattern|http://c2.com/cgi/wiki?PimplIdiom]]
Ongoing [[Builder]] activity especially can remould the Segmentation on a copy of the implementation structure, which is then swapped as a whole.
!Collecting usage scenarios {{red{WIP 12/10}}}
* ModelPort access
@ -2362,9 +2367,10 @@ To support this usage pattern, the Fixture implementation makes use of the [[PIm
** commit a transaction
!Conclusions about the structure {{red{WIP 12/10}}}
* the ~PImpl needs to be a single (language) pointer. This necessitates having a monolithic Fixture implementation holder
* moreover, this necessitates a tight integration down to implementation level, both with the clean-up and the render processes themselves
!Conclusions about the structure {{red{WIP 12/10 … update 4/23}}}
* the ~PImpl needs to be a single ''atomic pointer''. This necessitates having a monolithic Fixture implementation holder
* consequently we need a tailored memory management -- requiring some (limited) knowledge about the usage pattern
* this kind of information is available within the scheduling process ⟹ the [[Scheduler]] must support triggering on dependency events
</pre>
</div>
<div title="FixtureStorage" modifier="Ichthyostega" created="201012140231" modified="201403071814" tags="Builder impl operational draft" changecount="22">

View file

@ -69577,6 +69577,9 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742836996" ID="ID_1978512771" MODIFIED="1681742860339" TEXT="scaffolding and mocking used for this test">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1681742863121" ID="ID_101929835" MODIFIED="1681742878203" TEXT="ben&#xf6;tigte Mocks">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682611217967" ID="ID_792021380" MODIFIED="1682611222829" TEXT="Segmentation">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742879175" ID="ID_1375353236" MODIFIED="1681742901348" TEXT="Dispatcher">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1681743458393" ID="ID_891681445" MODIFIED="1681743469323" TEXT="extrahieren aus DispatcherInterface_test"/>
@ -69687,6 +69690,44 @@
<icon BUILTIN="full-3"/>
</node>
</node>
<node CREATED="1682611316697" ID="ID_296140708" MODIFIED="1682614014464" TEXT="Vorschau auf die Fixture-Datenstruktur">
<arrowlink COLOR="#735061" DESTINATION="ID_1136070257" ENDARROW="Default" ENDINCLINATION="-651;-968;" ID="Arrow_ID_1804652676" STARTARROW="None" STARTINCLINATION="-518;37;"/>
<icon BUILTIN="idea"/>
<node CREATED="1682613713646" ID="ID_1897977418" MODIFIED="1682613726321" TEXT="l&#xe4;uft auf eine Doppel-H&#xfc;lle hinaus"/>
<node CREATED="1682613727302" ID="ID_1816573739" MODIFIED="1682613737271" TEXT="wir implementieren im Moment nur einen Level"/>
<node CREATED="1682613738020" ID="ID_3577348" MODIFIED="1682613823627" TEXT="&#x27f9; Konsequenzen">
<node CREATED="1682613762760" ID="ID_970667296" MODIFIED="1682613815597" TEXT="Datenstruktur kann (bedenkenlos) direkt manipuliert werden">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682613782480" ID="ID_178794461" MODIFIED="1682614001907" TEXT="Split-and-Splice-Operation implementieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...das wird dann sp&#228;ter die Basis f&#252;r die Implementierung des Change-Builders
</p>
<ul>
<li>
diese Operation untersucht die bestehende Segmentation
</li>
<li>
und spaltet bestehende Segmente auf
</li>
<li>
sie kann unterscheiden zwischen Umbau(=replacement) und K&#252;rzen bzw. Klonen eines Segments
</li>
<li>
Schlu&#223;folgerung: ein Segment selbst darf nichts &#252;ber seine Zeitspanne wissen
</li>
</ul>
</body>
</html></richcontent>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
<node CREATED="1682384630010" ID="ID_1719484347" MODIFIED="1682385357439" TEXT="Struktur">
<icon BUILTIN="info"/>
<node CREATED="1682384645189" ID="ID_384048903" MODIFIED="1682384657607" TEXT="1 Record pro Segment">
@ -69821,6 +69862,13 @@
<node CREATED="1682385963140" ID="ID_1239158970" MODIFIED="1682385993315" TEXT="also MockSegmentation, MockJobTicket,..."/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682614081119" ID="ID_57760675" MODIFIED="1682614090109" TEXT="Interpretieren der jeweilgen Spec">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1682614092900" ID="ID_1252815318" MODIFIED="1682614105470" TEXT="Basis-Impl: ein Segment gibt es immer"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682614117409" ID="ID_1176991982" MODIFIED="1682614138327" TEXT="splitSplice() implementieren">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1682385895644" ID="ID_89969390" MODIFIED="1682385902557" TEXT="Verifikation im Test unterst&#xfc;tzen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1682386003212" ID="ID_930954734" MODIFIED="1682386014176" TEXT="gibt die &quot;Mock&quot;-Variante der jeweiligen Objekte heraus"/>
@ -70260,7 +70308,43 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1681742018442" ID="ID_596503548" MODIFIED="1681742022940" TEXT="Addressierung JobTicket">
<icon BUILTIN="flag-yellow"/>
</node>
<node CREATED="1682611423253" ID="ID_1136070257" MODIFIED="1682611949376" TEXT="Vorschau: Datenstruktur">
<linktarget COLOR="#735061" DESTINATION="ID_1136070257" ENDARROW="Default" ENDINCLINATION="-651;-968;" ID="Arrow_ID_1804652676" SOURCE="ID_296140708" STARTARROW="None" STARTINCLINATION="-518;37;"/>
<node CREATED="1682611979955" ID="ID_853916933" MODIFIED="1682611992260">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
es gibt einen <b>commit</b>
</p>
</body>
</html></richcontent>
<icon BUILTIN="yes"/>
</node>
<node CREATED="1682612009427" ID="ID_1994458742" MODIFIED="1682612053494" TEXT="vermutlich eine referentielle nicht-intrusive Linked-List">
<node CREATED="1682612056884" ID="ID_303611553" MODIFIED="1682612072158">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Eintr&#228;ge sind <i>woanders </i>alloziert
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1682612075770" ID="ID_1368353614" MODIFIED="1682612084845" TEXT="ein Eintrag kann in mehreren Instanzen der Liste liegen"/>
<node CREATED="1682612094504" ID="ID_250365879" MODIFIED="1682612109226" TEXT="&#x27f9; die umgebaute Liste kann auf einen Schlag aktualisiert werden"/>
</node>
<node CREATED="1682612125996" ID="ID_34027511" MODIFIED="1682612133736" TEXT="re-Partitionierung per Builder">
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node CREATED="1682611408260" ID="ID_408388335" MODIFIED="1682611410703" TEXT="Interface"/>
<node CREATED="1680563454868" ID="ID_1187556686" MODIFIED="1680563459014" TEXT="Backbone"/>
<node CREATED="1680563460649" ID="ID_127710483" MODIFIED="1680563474067" TEXT="MemManagement"/>
</node>