fill in ModelPort and ModelPortRegistry definition stubs

making test pass the compiler
This commit is contained in:
Fischlurch 2010-12-10 18:12:56 +01:00
parent 7043db90ee
commit 0464ca965c
6 changed files with 423 additions and 60 deletions

View file

@ -53,19 +53,176 @@
//using lumiera::Symbol; //using lumiera::Symbol;
namespace mobject { namespace mobject {
namespace builder { namespace builder {
/** /**
* TODO type comment * TODO type comment
*/ */
class ModelPortTable class ModelPortTable
: boost::noncopyable : boost::noncopyable
{ {
public:
};
public: typedef ModelPortRegistry::ModelPortDescriptor const& MPDescriptor;
};
inline MPDescriptor
accessDescriptor()
{
}
ModelPortRegistry&
ModelPortRegistry::setActiveInstance (ModelPortRegistry& newRegistry)
{
UNIMPLEMENTED ("handling of active model port registry");
}
/** */
ModelPortRegistry&
ModelPortRegistry::globalInstance()
{
UNIMPLEMENTED ("access the globally valid registry instance");
}
/** */
bool
ModelPortRegistry::contains (ID<Pipe> pID) const
{
UNIMPLEMENTED ("diagnostics querying the state of the pending transaction");
}
/** @return true if the given pipe-ID actually denotes an
* existing, connected and usable model port.
* @note reflects the state of the publicly visible
* model port registry, \em not any model ports
* being registered within a currently pending
* transaction (ongoing build process). */
bool
ModelPortRegistry::isRegistered (ID<Pipe> key) const
{
if (!key) return false;
UNIMPLEMENTED ("query the publicly valid contents");
}
/** */
MPDescriptor
ModelPortRegistry::operator[] (ID<Pipe> key) const
{
UNIMPLEMENTED ("access registered model port");
}
/** */
MPDescriptor
ModelPortRegistry::accessDescriptor (ID<Pipe> key)
{
UNIMPLEMENTED ("access the current global registry and fetch model port");
}
/** */
MPDescriptor
ModelPortRegistry::definePort (ID<Pipe> pipeA, ID<Struct> element_exposing_this_port)
{
UNIMPLEMENTED ("create and register a new model port entry, within the pending transaction");
}
/** */
void
ModelPortRegistry::remove (PID key)
{
UNIMPLEMENTED ("remove a model port entry from the pending transaction");
}
/** */
void
ModelPortRegistry::clear()
{
UNIMPLEMENTED ("schedule removal of all registry contents into the pending transaction");
}
/** */
void
ModelPortRegistry::commit()
{
UNIMPLEMENTED ("transactional switch for new/modified model ports");
}
/** */
void
ModelPortRegistry::rollback()
{
UNIMPLEMENTED ("discard current transaction");
}
LUMIERA_ERROR_DEFINE (DUPLICATE_MODEL_PORT, "Attempt to define a new model port with an pipe-ID already denoting an existing port");
} // namespace builder
}} // namespace mobject
LUMIERA_ERROR_DEFINE (INVALID_MODEL_PORT, "Referral to unknown model port");
LUMIERA_ERROR_DEFINE (UNCONNECTED_MODEL_PORT, "Attempt to operate on an existing but unconnected model port");
ModelPort::ModelPort (ID<asset::Pipe> refID)
: id_(refID)
{
builder::ModelPortRegistry::accessDescriptor (refID);
}
/** */
bool
ModelPort::exists (ID<asset::Pipe> key)
{
return builder::ModelPortRegistry::globalInstance().isRegistered (key);
}
/** */
ID<asset::Pipe>
ModelPort::pipe() const
{
ENSURE (this->id_ == builder::ModelPortRegistry::accessDescriptor(this->id_).id);
return builder::ModelPortRegistry::accessDescriptor(this->id_).id;
}
/** */
ID<asset::Struct>
ModelPort::holder() const
{
return builder::ModelPortRegistry::accessDescriptor(this->id_).holder;
}
/** */
StreamType::ID
ModelPort::streamType() const
{
return this->id_.streamType();
}
} // namespace mobject

View file

@ -34,8 +34,6 @@
** for setting up such a registry, while all other parts of the system just access the current ** for setting up such a registry, while all other parts of the system just access the current
** model ports through the mobject::ModelPort frontend. ** model ports through the mobject::ModelPort frontend.
** **
** TODO fill in more details?
**
** @see ModelPort ** @see ModelPort
** @see OutputDesignation ** @see OutputDesignation
** @see ModelPortRegistry_test ** @see ModelPortRegistry_test
@ -45,7 +43,11 @@
#ifndef PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H #ifndef PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H
#define PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H #define PROC_MOBJECT_BUILDER_MODEL_PORT_REGISTRY_H
#include "lib/error.hpp"
#include "proc/asset/pipe.hpp" #include "proc/asset/pipe.hpp"
#include "proc/asset/struct.hpp"
#include "proc/mobject/model-port.hpp"
//#include "lib/opaque-holder.hpp" //#include "lib/opaque-holder.hpp"
//#include "lib/meta/typelist-util.hpp" //#include "lib/meta/typelist-util.hpp"
@ -56,17 +58,105 @@
namespace mobject { namespace mobject {
namespace builder { namespace builder {
using asset::ID;
using asset::Pipe;
//using asset::PPipe;
using asset::Struct;
LUMIERA_ERROR_DECLARE (DUPLICATE_MODEL_PORT); ///< Attempt to define a new model port with an pipe-ID already denoting an existing port
/** /**
* TODO type comment * Management facility for tracking model ports.
* ModelPort handles are exposed as frontend for usage
* by client code. Model ports are discovered by the builder
* when re-creating the low-level model; during such an ongoing
* build process, newly discovered ports are accumulated within
* a transaction, which then gets committed atomically when the
* new model is complete and ready for use.
*/ */
class ModelPortRegistry class ModelPortRegistry
: boost::noncopyable : boost::noncopyable
{ {
typedef ID<Pipe> PID;
typedef ID<Struct> StID;
public: public:
/** @internal record to describe a model port */
struct ModelPortDescriptor;
static ModelPortRegistry&
setActiveInstance (ModelPortRegistry& newRegistry);
static ModelPortRegistry&
globalInstance();
static ModelPortDescriptor const&
accessDescriptor (PID);
ModelPortDescriptor const&
definePort (PID pipe, StID element_exposing_this_port);
bool contains (PID) const;
bool isRegistered (PID) const;
ModelPortDescriptor const&
operator[] (PID) const;
void remove (PID);
void clear();
/** activate pending model port changes.
* Any accumulated changes and newly defined model ports
* are promoted to become part of the current active configuration
* with a single atomic (transactional) switch.
*/
void commit();
/** discard pending changes.
* Silently drop model port definition changes since the last commit.
*/
void rollback();
}; };
/** ModelPortDescriptor records are used as actual storage
* within the model port registration table; they are never
* exposed to client code directly.
*/
struct ModelPortRegistry::ModelPortDescriptor
{
const PID id;
const StID holder;
bool
isValid() const
{
return bool(id);
}
ModelPortDescriptor()
: id(PID::INVALID)
, holder(StID::INVALID)
{ }
// default copy operations permitted
protected:
ModelPortDescriptor (PID pipe, StID element_exposing_this_port)
: id(pipe)
, holder(element_exposing_this_port)
{ }
};
}} // namespace mobject::builder }} // namespace mobject::builder
#endif #endif

View file

@ -30,7 +30,7 @@
** and low-level view. A model port can be associated both to a pipe within a timeline ** and low-level view. A model port can be associated both to a pipe within a timeline
** in the HighLevelModel, as well as to denote a set of corresponding exit nodes within ** in the HighLevelModel, as well as to denote a set of corresponding exit nodes within
** the segments of the render nodes network. Model ports are keyed by Pipe-ID and thus ** the segments of the render nodes network. Model ports are keyed by Pipe-ID and thus
** are unique within the application. ** are bound to be unique within the application.
** **
** A model port is rather derived than configured; it emerges during the build process ** A model port is rather derived than configured; it emerges during the build process
** when a pipe claims an OutputDesignation and some other entity actually uses this ** when a pipe claims an OutputDesignation and some other entity actually uses this
@ -41,21 +41,22 @@
** **
** Because model ports are discovered this way, dynamically during the build process, ** Because model ports are discovered this way, dynamically during the build process,
** at some point there is a <i>transactional switch</i> to promote the new configuration ** at some point there is a <i>transactional switch</i> to promote the new configuration
** to be come the valid current model port configuration. After that switch, model ports ** to become the valid current model port configuration. After that switch, model ports
** are immutable. ** are immutable.
** **
** Model ports are to be accessed, enumerated and grouped in various ways, because each ** Model ports are to be accessed, enumerated and grouped in various ways, because each
** port belongs to a specific timeline and is used for producing data of a single ** port belongs to a specific timeline and is used for producing data of a single
** StreamType solely. But all those referrals, searching and grouping happens only ** StreamType solely. But all those referrals, searching and grouping happens only
** after the build process has discovered all model ports currently available. ** after the build process has discovered all model ports currently available.
** Thus we provide a MPortRef smart-pointer to ease handling of those access ** Thus actually the ModelPort elements handed out to client code are just
** operations. The actual model port descriptors are owned and managed by ** smart-handles, accessing a global ModelPortRegistry behind the scenes.
** the fixture; they are bulk allocated in a similar manner than the ** Validity of these handles will be checked on each access. The actual
** model port descriptors are owned and managed by the fixture;
** they are bulk allocated in a similar manner than the
** ProcNode and WiringDescriptor objects. ** ProcNode and WiringDescriptor objects.
** **
** TODO fill in more details? ** @see ModelPortRegistry_test abstract usage example
** TODO where to put the ModelPortTable ** @see ModelPortRegistry management interface
**
** @see OutputDesignation ** @see OutputDesignation
** @see OutputMapping ** @see OutputMapping
** @see Timeline ** @see Timeline
@ -66,23 +67,83 @@
#define PROC_MOBJECT_MODEL_PORT_H #define PROC_MOBJECT_MODEL_PORT_H
#include "proc/asset/pipe.hpp" #include "proc/asset/pipe.hpp"
//#include "lib/opaque-holder.hpp" #include "lib/bool-checkable.hpp"
//#include "lib/meta/typelist-util.hpp" #include "lib/streamtype.hpp"
//extern "C" {
//#include "lib/luid.h"
//}
namespace mobject { namespace mobject {
LUMIERA_ERROR_DECLARE (INVALID_MODEL_PORT); ///< Referral to unknown model port
LUMIERA_ERROR_DECLARE (UNCONNECTED_MODEL_PORT); ///< Attempt to operate on an existing but unconnected model port
using asset::ID;
using lumiera::StreamType;
/** /**
* TODO type comment * Handle denoting a port within the model,
* where actually output data can be pulled.
* ModelPort is a frontend to be used by clients.
* These ModelPort handle objects may be copied and stored
* at will, but their validity will be verified on each access.
* Actually, the Builder will discover any model ports and
* maintain a ModelPortRegistry behind the scenes.
*
* Each model port corresponds to a (global) pipe within a
* specific Timeline; consequently each such port is also
* bound to produce data of a specific StreamType (as defined by
* the corresponding pipe). A model port may be in \em unconnected
* state, which can be checked by \c bool conversion. While the
* ModelPort handles are value objects, the identity of the
* underlying model port (descriptor) is given by the
* corresponding pipe-ID, thus effectively resulting
* in a global namespace for model ports.
*
* @see builder::ModelPortRegistry management interface
* @see ModelPortRegistry_test abstract usage example
*/ */
class ModelPort class ModelPort
: boost::noncopyable : public lib::BoolCheckable<ModelPort>
{ {
ID<asset::Pipe> id_;
public: public:
ModelPort() ///< \em unconnected model port
: id_(ID<asset::Pipe>::INVALID)
{ }
ModelPort (ID<asset::Pipe> refID); ///< @note conversion from pipe-ID
// using default copy operations
static bool exists (ID<asset::Pipe>);
ID<asset::Pipe> pipe() const;
ID<asset::Struct> holder() const;
StreamType::ID streamType() const;
bool
isValid() const
{
return exists (this->id_);
}
friend bool
operator== (ModelPort const& mp1, ModelPort const& mp2)
{
return mp1.id_ == mp2.id_;
}
friend bool
operator!= (ModelPort const& mp1, ModelPort const& mp2)
{
return mp1.id_ != mp2.id_;
}
private:
}; };

View file

@ -15,6 +15,11 @@ PLANNED "BuildSegment_test" BuildSegment_test <<END
END END
PLANNED "ModelPort registry" ModelPortRegistry_test <<END
return: 0
END
TEST "Output pipe mapping" OutputMapping_test <<END TEST "Output pipe mapping" OutputMapping_test <<END
return: 0 return: 0
END END

View file

@ -73,6 +73,7 @@ test_components_SOURCES = \
$(testcomponents_srcdir)/proc/engine/node-source-test.cpp \ $(testcomponents_srcdir)/proc/engine/node-source-test.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \ $(testcomponents_srcdir)/proc/mobject/builder/buildertooltest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/buildsegmenttest.cpp \ $(testcomponents_srcdir)/proc/mobject/builder/buildsegmenttest.cpp \
$(testcomponents_srcdir)/proc/mobject/builder/model-port-registry-test.cpp \
$(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \ $(testcomponents_srcdir)/proc/mobject/controller/rendersegmenttest.cpp \
$(testcomponents_srcdir)/proc/mobject/mobject-interface-test.cpp \ $(testcomponents_srcdir)/proc/mobject/mobject-interface-test.cpp \
$(testcomponents_srcdir)/proc/mobject/mobject-ref-test.cpp \ $(testcomponents_srcdir)/proc/mobject/mobject-ref-test.cpp \

View file

@ -25,29 +25,52 @@
#include "lib/test/test-helper.hpp" #include "lib/test/test-helper.hpp"
#include "proc/mobject/builder/model-port-registry.hpp" #include "proc/mobject/builder/model-port-registry.hpp"
#include "proc/asset/pipe.hpp" #include "proc/asset/pipe.hpp"
#include "proc/asset/timeline.hpp"
#include "lib/query.hpp"
#include "lib/util.hpp" #include "lib/util.hpp"
//#include <boost/format.hpp> //#include <boost/format.hpp>
//#include <boost/scoped_ptr.hpp> //#include <boost/scoped_ptr.hpp>
#include <string> #include <string>
//using boost::format;
//using boost::scoped_ptr;
using util::isSameObject;
using util::isnil;
using std::string;
namespace mobject { namespace mobject {
namespace builder { namespace builder {
namespace test { namespace test {
//using boost::format;
//using boost::scoped_ptr;
using util::isSameObject;
using util::isnil;
using std::string;
using asset::Pipe; using asset::Pipe;
using asset::PPipe; using asset::PPipe;
using asset::Struct;
using asset::Timeline;
using asset::PTimeline;
using lumiera::Query;
typedef asset::ID<Pipe> PID;
typedef asset::ID<Struct> TID;
//typedef asset::ID<Pipe> PID;
namespace { // test environment namespace { // test environment
inline PID
getPipe (string id)
{
return Pipe::query("id("+id+")");
}
inline TID
getTimeline (string id)
{
return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
}
typedef ModelPortRegistry::ModelPortDescriptor const& MPDescriptor;
struct TestContext struct TestContext
{ {
ModelPortRegistry registry_; ModelPortRegistry registry_;
@ -88,30 +111,35 @@ namespace test {
{ {
TestContext ctx; TestContext ctx;
fabricating_ModelPorts (ctx); fabricating_ModelPorts (ctx.registry_);
accessing_ModelPorts(); accessing_ModelPorts();
transactionalSwitch (ctx); transactionalSwitch (ctx.registry_);
} }
void void
fabricating_ModelPorts (ModelPortRegistry& registry) fabricating_ModelPorts (ModelPortRegistry& registry)
{ {
ModelPortDescriptor& p1 = registry.definePort (pipeA, someTimeline); /* == some Assets to play with == */
ModelPortDescriptor& p2 = registry.definePort (pipeB, someTimeline); PID pipeA = getPipe ("pipeA");
PID pipeB = getPipe ("pipeB");
PID pipeWC = getPipe ("WCpipe");
TID someTimeline = getTimeline ("some_test_Timeline");
CHECK (p1); // start out with defining some new model ports......
CHECK (p2); MPDescriptor p1 = registry.definePort (pipeA, someTimeline);
MPDescriptor p2 = registry.definePort (pipeB, someTimeline);
CHECK (registry.contains (pipeA));
CHECK (registry.contains (pipeB));
VERIFY_ERROR (DUPLICATE_MODEL_PORT, registry.definePort(pipeB, someTimeline) ); VERIFY_ERROR (DUPLICATE_MODEL_PORT, registry.definePort(pipeB, someTimeline) );
CHECK (p2); CHECK (registry.contains (pipeB));
CHECK (p1.getID() == pipeA); CHECK (p1.id == pipeA);
CHECK (p2.getID() == pipeB); CHECK (p2.id == pipeB);
CHECK (p1.getPipe() == pipeA); CHECK (p1.holder == someTimeline);
CHECK (p2.getPipe() == pipeB); CHECK (p2.holder == someTimeline);
CHECK (p1.getTimeline() == someTimeline);
CHECK (p2.getTimeline() == someTimeline);
registry.commit(); registry.commit();
} }
@ -120,6 +148,10 @@ namespace test {
void void
accessing_ModelPorts () accessing_ModelPorts ()
{ {
PID pipeA = getPipe ("pipeA");
PID pipeB = getPipe ("pipeB");
PID pipeWC = getPipe ("WCpipe");
ModelPort mp1(pipeA); ModelPort mp1(pipeA);
ModelPort mp2(pipeB); ModelPort mp2(pipeB);
@ -149,26 +181,32 @@ namespace test {
CHECK (mp1x.pipe() == pipeA); CHECK (mp1x.pipe() == pipeA);
VERIFY_ERROR (UNCONNECTED_MODEL_PORT, mpNull.pipe()); VERIFY_ERROR (UNCONNECTED_MODEL_PORT, mpNull.pipe());
CHECK (mp1.streamType() == pipeA.getStreamType()); CHECK (mp1.streamType() == pipeA.streamType());
} }
void void
transactionalSwitch (ModelPortRegistry& registry) transactionalSwitch (ModelPortRegistry& registry)
{ {
PID pipeA = getPipe ("pipeA");
PID pipeB = getPipe ("pipeB");
PID pipeWC = getPipe ("WCpipe");
CHECK ( ModelPort::exists (pipeB)); CHECK ( ModelPort::exists (pipeB));
CHECK (!ModelPort::exists (pipeWC)); CHECK (!ModelPort::exists (pipeWC));
CHECK (ModelPort::exists (pipeA)); CHECK (ModelPort::exists (pipeA));
CHECK (registry.contains (pipeA)); CHECK (registry.contains (pipeA));
registry.remove (pipeA); registry.remove (pipeA);
CHECK (ModelPort::exists (pipeA)); CHECK ( ModelPort::exists (pipeA));
CHECK (!registry.contains (pipeA)); CHECK (!registry.contains (pipeA));
ModelPortDescriptor& p1 = registry.definePort (pipeA, anotherTimeline); // now create a new and differing definition of port A
TID anotherTimeline = getTimeline ("another_test_Timeline");
MPDescriptor p1 = registry.definePort (pipeA, anotherTimeline);
CHECK (registry.contains (pipeA)); CHECK (registry.contains (pipeA));
CHECK (p1.getTimeline() == anotherTimeline); CHECK (p1.holder == anotherTimeline);
CHECK (ModelPort(pipeA).timeline() != anotherTimeline); CHECK (ModelPort(pipeA).holder() != anotherTimeline);
registry.remove (pipeB); registry.remove (pipeB);
registry.definePort (pipeWC,anotherTimeline); registry.definePort (pipeWC,anotherTimeline);
@ -184,7 +222,7 @@ namespace test {
CHECK (portB); CHECK (portB);
CHECK (portA.pipe() == pipeA); CHECK (portA.pipe() == pipeA);
CHECK (portB.pipe() == pipeB); CHECK (portB.pipe() == pipeB);
CHECK (portA.timeline() != anotherTimeline); CHECK (portA.holder() != anotherTimeline);
registry.commit(); registry.commit();
CHECK ( ModelPort::exists (pipeA)); CHECK ( ModelPort::exists (pipeA));
@ -192,14 +230,25 @@ namespace test {
CHECK ( ModelPort::exists (pipeWC)); CHECK ( ModelPort::exists (pipeWC));
CHECK ( portA); CHECK ( portA);
CHECK (!portB); CHECK (!portB);
CHECK (portA.timeline() == anotherTimeline); CHECK (portA.holder() == anotherTimeline);
CHECK (portA.pipe() == pipeA); CHECK (portA.pipe() == pipeA);
VERIFY_ERROR (UNCONNECTED_MODEL_PORT, portB.pipe()); VERIFY_ERROR (UNCONNECTED_MODEL_PORT, portB.pipe());
ModelPort pwc(pipeWC); ModelPort pwc(pipeWC);
CHECK (pwc); CHECK (pwc);
CHECK (pwc.pipe() == pipeWC); CHECK (pwc.pipe() == pipeWC);
CHECK (pwc.timeline() == anotherTimeline); CHECK (pwc.holder() == anotherTimeline);
registry.remove (pipeA);
registry.clear();
CHECK (!registry.contains (pipeA));
CHECK (!registry.contains (pipeB));
CHECK (!registry.contains (pipeWC));
registry.rollback();
CHECK ( registry.contains (pipeA));
CHECK ( registry.contains (pipeB));
CHECK ( registry.contains (pipeWC));
} }
}; };