WIP: test driven brainstorming about model port registry
This commit is contained in:
parent
8802beb753
commit
2827961385
4 changed files with 297 additions and 9 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
ModelPort - point to pull output data from the model
|
||||
ModelPortRegistry - creating and organising and accessing model ports
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
* *****************************************************/
|
||||
|
||||
|
||||
/** @file model-port.cpp
|
||||
/** @file model-port-registry.cpp
|
||||
** Implementation details of model port descriptors and references.
|
||||
** Especially, the handling of the ModelPortTable datastructure is
|
||||
** kept an opaque implementation detail and confined entirely within
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
#include "lib/error.hpp"
|
||||
//#include "lib/symbol.hpp"//
|
||||
#include "proc/mobject/model-port.hpp"
|
||||
#include "proc/mobject/builder/model-port-registry.hpp"
|
||||
|
||||
//#include <boost/functional/hash.hpp>
|
||||
//#include <cstdlib>
|
||||
|
|
@ -52,6 +53,7 @@
|
|||
//using lumiera::Symbol;
|
||||
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -66,4 +68,4 @@ namespace mobject {
|
|||
|
||||
|
||||
|
||||
} // namespace mobject
|
||||
}} // namespace mobject
|
||||
72
src/proc/mobject/builder/model-port-registry.hpp
Normal file
72
src/proc/mobject/builder/model-port-registry.hpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
MODEL-PORT-REGISTRY.hpp - creating and organising and accessing model ports
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, 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 model-port-registry.hpp
|
||||
** Mutation and management facility for model ports within the builder.
|
||||
** Model ports denote the points where output might possibly be produced.
|
||||
** While client code accesses model ports only as immutable descriptors handled
|
||||
** through an (opaque) reference, the builder is in charge of detecting and organising
|
||||
** any (new) model ports arising as the result of the build process. Changes to the set
|
||||
** of current model ports are to be activated with an atomic <i>transactional switch.</i>
|
||||
**
|
||||
** builder::ModelPortRegistry thus acts as management interface and factory for model ports.
|
||||
** A given instance of this registry can be promoted to be "the" model port registry reflecting
|
||||
** the current active model ports. Within the Lumiera application, the builder subsystem cares
|
||||
** for setting up such a registry, while all other parts of the system just access the current
|
||||
** model ports through the mobject::ModelPort frontend.
|
||||
**
|
||||
** TODO fill in more details?
|
||||
**
|
||||
** @see ModelPort
|
||||
** @see OutputDesignation
|
||||
** @see ModelPortRegistry_test
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H
|
||||
#define PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H
|
||||
|
||||
#include "proc/asset/pipe.hpp"
|
||||
//#include "lib/opaque-holder.hpp"
|
||||
//#include "lib/meta/typelist-util.hpp"
|
||||
|
||||
//extern "C" {
|
||||
//#include "lib/luid.h"
|
||||
//}
|
||||
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
/**
|
||||
* TODO type comment
|
||||
*/
|
||||
class ModelPortRegistry
|
||||
: boost::noncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace mobject::builder
|
||||
#endif
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
ModelPortRegistry(Test) - verify handling of model ports
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2010, 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.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "proc/mobject/builder/model-port-registry.hpp"
|
||||
#include "proc/asset/pipe.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/format.hpp>
|
||||
//#include <boost/scoped_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
//using boost::format;
|
||||
//using boost::scoped_ptr;
|
||||
using util::isSameObject;
|
||||
using util::isnil;
|
||||
using std::string;
|
||||
|
||||
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
namespace test {
|
||||
|
||||
using asset::Pipe;
|
||||
using asset::PPipe;
|
||||
|
||||
//typedef asset::ID<Pipe> PID;
|
||||
namespace { // test environment
|
||||
|
||||
struct TestContext
|
||||
{
|
||||
ModelPortRegistry registry_;
|
||||
ModelPortRegistry& previous_;
|
||||
|
||||
/** setup */
|
||||
TestContext()
|
||||
: registry_()
|
||||
, previous_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
{ }
|
||||
|
||||
/** tear-down */
|
||||
~TestContext()
|
||||
{
|
||||
ModelPortRegistry::setActiveInstance (previous_);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
* @test create a standalone model port registry to verify the behaviour of
|
||||
* model ports, accessed through reference handles. This test provides
|
||||
* an example setup detached from the real usage situation within the builder.
|
||||
* The ModelPortRegistry management interface is used to create and track a
|
||||
* set of model ports, to be made visible by an atomic, transactional switch.
|
||||
* The access for client code through the ModelPort frontend is then verified.
|
||||
*
|
||||
* @see mobject::ModelPort
|
||||
* @see mobject::builder::ModelPortRegistry
|
||||
*/
|
||||
class ModelPortRegistry_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
TestContext ctx;
|
||||
|
||||
fabricating_ModelPorts (ctx);
|
||||
accessing_ModelPorts();
|
||||
transactionalSwitch (ctx);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fabricating_ModelPorts (ModelPortRegistry& registry)
|
||||
{
|
||||
ModelPortDescriptor& p1 = registry.definePort (pipeA, someTimeline);
|
||||
ModelPortDescriptor& p2 = registry.definePort (pipeB, someTimeline);
|
||||
|
||||
CHECK (p1);
|
||||
CHECK (p2);
|
||||
|
||||
VERIFY_ERROR (DUPLICATE_MODEL_PORT, registry.definePort(pipeB, someTimeline) );
|
||||
CHECK (p2);
|
||||
|
||||
CHECK (p1.getID() == pipeA);
|
||||
CHECK (p2.getID() == pipeB);
|
||||
CHECK (p1.getPipe() == pipeA);
|
||||
CHECK (p2.getPipe() == pipeB);
|
||||
CHECK (p1.getTimeline() == someTimeline);
|
||||
CHECK (p2.getTimeline() == someTimeline);
|
||||
|
||||
registry.commit();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
accessing_ModelPorts ()
|
||||
{
|
||||
ModelPort mp1(pipeA);
|
||||
ModelPort mp2(pipeB);
|
||||
|
||||
VERIFY_ERROR (INVALID_MODEL_PORT, ModelPort(pipeWC));
|
||||
|
||||
ModelPort mp1x(pipeA);
|
||||
ModelPort mpNull;
|
||||
|
||||
CHECK (mp1);
|
||||
CHECK (mp2);
|
||||
CHECK (mp1x);
|
||||
CHECK (!mpNull);
|
||||
|
||||
CHECK ( ModelPort::exists (pipeA));
|
||||
CHECK ( ModelPort::exists (pipeB));
|
||||
CHECK (!ModelPort::exists (pipeWC));
|
||||
|
||||
CHECK (mp1 == mp1x);
|
||||
CHECK (!isSameObject (mp1, mp1x));
|
||||
CHECK (mp1 != mp2);
|
||||
CHECK (mp2 != mp1);
|
||||
CHECK (mp1 != mpNull);
|
||||
CHECK (mp2 != mpNull);
|
||||
|
||||
CHECK (mp1.pipe() == pipeA);
|
||||
CHECK (mp2.pipe() == pipeB);
|
||||
CHECK (mp1x.pipe() == pipeA);
|
||||
VERIFY_ERROR (UNCONNECTED_MODEL_PORT, mpNull.pipe());
|
||||
|
||||
CHECK (mp1.streamType() == pipeA.getStreamType());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
transactionalSwitch (ModelPortRegistry& registry)
|
||||
{
|
||||
CHECK ( ModelPort::exists (pipeB));
|
||||
CHECK (!ModelPort::exists (pipeWC));
|
||||
|
||||
CHECK (ModelPort::exists (pipeA));
|
||||
CHECK (registry.contains (pipeA));
|
||||
registry.remove (pipeA);
|
||||
CHECK (ModelPort::exists (pipeA));
|
||||
CHECK (!registry.contains (pipeA));
|
||||
|
||||
ModelPortDescriptor& p1 = registry.definePort (pipeA, anotherTimeline);
|
||||
CHECK (registry.contains (pipeA));
|
||||
CHECK (p1.getTimeline() == anotherTimeline);
|
||||
CHECK (ModelPort(pipeA).timeline() != anotherTimeline);
|
||||
|
||||
registry.remove (pipeB);
|
||||
registry.definePort (pipeWC,anotherTimeline);
|
||||
CHECK (!registry.contains (pipeB));
|
||||
CHECK ( registry.contains (pipeWC));
|
||||
CHECK ( ModelPort::exists (pipeB));
|
||||
CHECK (!ModelPort::exists (pipeWC));
|
||||
|
||||
ModelPort portA(pipeA);
|
||||
ModelPort portB(pipeB);
|
||||
VERIFY_ERROR (INVALID_MODEL_PORT, ModelPort(pipeWC));
|
||||
CHECK (portA);
|
||||
CHECK (portB);
|
||||
CHECK (portA.pipe() == pipeA);
|
||||
CHECK (portB.pipe() == pipeB);
|
||||
CHECK (portA.timeline() != anotherTimeline);
|
||||
|
||||
registry.commit();
|
||||
CHECK ( ModelPort::exists (pipeA));
|
||||
CHECK (!ModelPort::exists (pipeB));
|
||||
CHECK ( ModelPort::exists (pipeWC));
|
||||
CHECK ( portA);
|
||||
CHECK (!portB);
|
||||
CHECK (portA.timeline() == anotherTimeline);
|
||||
CHECK (portA.pipe() == pipeA);
|
||||
VERIFY_ERROR (UNCONNECTED_MODEL_PORT, portB.pipe());
|
||||
|
||||
ModelPort pwc(pipeWC);
|
||||
CHECK (pwc);
|
||||
CHECK (pwc.pipe() == pipeWC);
|
||||
CHECK (pwc.timeline() == anotherTimeline);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (ModelPortRegistry_test, "unit session builder");
|
||||
|
||||
|
||||
|
||||
}}} // namespace mobject::builder::test
|
||||
|
|
@ -1786,20 +1786,20 @@ Some further details
|
|||
* a special case of this factory use is the [[Singleton]] factory, which is used a lot within the Proy-Layer code
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Fixture" modifier="Ichthyostega" modified="201012030310" created="200706220324" tags="def spec Builder Model" changecount="42">
|
||||
<div title="Fixture" modifier="Ichthyostega" modified="201012092320" created="200706220324" tags="def spec Builder Model" changecount="44">
|
||||
<pre>a specially configured view -- joining together high-level and low-level model
|
||||
* all MObjects have their position, length and configuration set up ready for rendering.
|
||||
* any nested sequences (or other kinds of indirections) have been resolved.
|
||||
* every MObject is attached by an ExplicitPlacement, which declares a fixed position (Time, [[Pipe|OutputDesignation]])
|
||||
* these ~ExplicitPlacements are contained immediately within the Fixture, ordered by time
|
||||
* besides, there is a collection of all effective, possibly externally visible [[model ports|ModelPort]]
|
||||
* besides, there is a collection of all effective, possibly externally visible [[model ports|ModelPortRegistry]]
|
||||
|
||||
As the builder and thus render engine //only consults the fixture,// while all editing operations finally propagate to the fixture as well, we get an isolation layer between the high level part of the Proc layer (editing, object manipulation) and the render engine. [[Creating the Fixture|BuildFixture]] is an important sideeffect of running the [[Builder]] when createing the [[render engine network|LowLevelModel]].
|
||||
|
||||
!{{red{WIP}}} Structure of the fixture
|
||||
[<img[Structure of the Fixture|draw/Fixture1.png]]
|
||||
|
||||
The fixture is like a grid, where one dimension is given by the [[model ports|ModelPortTable]], and the other dimension extends in time. Within the time dimension there is a grouping into [[segments|Segmentation]] of constant structure.
|
||||
The fixture is like a grid, where one dimension is given by the [[model ports|ModelPortRegistry]], and the other dimension extends in time. Within the time dimension there is a grouping into [[segments|Segmentation]] of constant structure.
|
||||
|
||||
;Model Ports
|
||||
:The model ports share a single uniform and global name space: actually they're keyed by ~Pipe-ID
|
||||
|
|
@ -2819,8 +2819,8 @@ These are used as token for dealing with other objects and have no identity of t
|
|||
|
||||
</pre>
|
||||
</div>
|
||||
<div title="ModelPort" modifier="Ichthyostega" modified="201012030404" created="201011100234" tags="def spec" changecount="5">
|
||||
<pre>Any point where output possibly might be produced. Model port entities are located within the [[Fixture]] &mdash; model port as a concept spans the high-level and low-level view. A model port can be associated both to a pipe in the HighLevelModel but at the same time denote a set of corresponding [[exit nodes|ExitNode]] within the [[segments|Segmentation]] of the render nodes network.
|
||||
<div title="ModelPort" modifier="Ichthyostega" modified="201012091252" created="201011100234" tags="def spec" changecount="6">
|
||||
<pre>Any point where output possibly might be produced. Model port entities are located within the [[Fixture]] &mdash; model port as a concept spans the high-level and low-level view. A model port can be associated both to a pipe in the HighLevelModel but at the same time denotes a set of corresponding [[exit nodes|ExitNode]] within the [[segments|Segmentation]] of the render nodes network.
|
||||
|
||||
A model port is rather derived than configured; it emerges when a pipe [[claims|WiringClaim]] an output destination and some other entity actually uses this designation as a target, either directly or indirectly. This match of provision and usage is detected during the build process and produces an entry in the fixture's model port table. These model ports in the fixture are keyed by ~Pipe-ID, thus each model port has an associated StreamType.
|
||||
|
||||
|
|
@ -2833,7 +2833,7 @@ Model ports are represented by small non-copyable descriptor objects with distin
|
|||
|
||||
</pre>
|
||||
</div>
|
||||
<div title="ModelPortTable" modifier="Ichthyostega" modified="201012030345" created="201012030314" tags="Model impl" changecount="2">
|
||||
<div title="ModelPortRegistry" modifier="Ichthyostega" modified="201012092325" created="201012030314" tags="Model impl" changecount="2">
|
||||
<pre>Model ports are conceptual entities, denoting the points where output might possibly be produced &rarr; see [[definition|ModelPort]].
|
||||
But there is an actual representation, a collection of small descriptor objects managed by the Fixture and organised within the model port table datastructure. Because model ports are discovered during the build process, we need the ability to (re)build this table dynamically, finally swapping in the modified configuration with a transactional switch. Only the builder is allowed to perform such mutations, while for client code model ports are immutable.
|
||||
|
||||
|
|
@ -2852,6 +2852,8 @@ Model ports are added once and never changed. The corresponding timeline and pip
|
|||
The transactional switch creates a clear partitioning in the lifespan of the model port table. //Before// that point, entries are just added, but not accessed in any way. //After// that point, no further mutation occurs, but lookup is frequent and happens in a variety of different configurations and transient orderings.
|
||||
|
||||
This observation leads to the idea of using //model port references// to provide all kinds of access, searching and reordering. These encapsulate the actual access by silently assuming reference to "the" global current model port configuration. Thus, the actual model port descriptors could be bulk allocated in a similar manner as the processing nodes and wiring descriptors. Access to stale model ports could be detected by the port references, allowing also for a {{{bool}}} checkable "has no port" information.
|
||||
|
||||
A model port registry, maintained by the builder, is responsible for storing the discovered model ports within a model port table, which is then swapped in after completing the build process. The {{{builder::ModelPortRegistry}}} acts as management interface, while client code accesses just the {{{ModelPort}}} frontend. A link to the actual registry instance is hooked into that frontend when bringing up the builder subsystem.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="ModelRootMO" modifier="Ichthyostega" modified="200912110245" created="200912080307" tags="def" changecount="5">
|
||||
|
|
|
|||
Loading…
Reference in a new issue