OutputMapping implementation draft

coded up the easy part, omitting the actual resolution
based on an configuration query
This commit is contained in:
Fischlurch 2010-11-27 06:01:31 +01:00
parent 1e2d4d90f6
commit fc051dfcba
2 changed files with 99 additions and 40 deletions

View file

@ -28,9 +28,11 @@
#include "lib/meta/function.hpp"
#include "lib/bool-checkable.hpp"
#include "lib/query.hpp"
#include "lib/util.hpp"
#include <boost/noncopyable.hpp>
#include <boost/operators.hpp>
#include <map>
@ -39,6 +41,7 @@ namespace mobject {
namespace { // Helper to extract and rebind definition types
using std::tr1::function;
using util::contains;
template<class DEF>
class _def
@ -66,6 +69,7 @@ namespace mobject {
}
using lumiera::Query;
using asset::HashVal;
/**
@ -75,68 +79,100 @@ namespace mobject {
* type of the target specification is defined
* through the type parameter.
*
* This is an Interface, intended to be used in the signature
* of API functions either providing or requiring a Mapping.
* \par definition of specific mapping behaviour
*
* This is an generic map-like container, acting as Interface to be used
* in the signature of API functions either providing or requiring a Mapping.
* For each distinct usage situation, an instantiation of this template should
* be created, providing a <i>definition context</i> as template parameter.
* Instances of this concrete mapping type may then be default constructed
* and copied freely. The definition context is supposed to provide
* - a functor \c DEF::output usable as function pipe-ID --> Target
* - the concrete output-functor also defines the concrete Target type,
* which will be returned when accessing the OutputMapping
*/
template<class DEF>
class OutputMapping
: public DEF
{
typedef _def<DEF> Setup;
typedef asset::ID<asset::Pipe> PId;
typedef asset::PPipe PPipe;
/* == mapping table storage == */
std::map<HashVal,HashVal> table_;
public:
typedef typename Setup::Target Target;
size_t
size() const
{
UNIMPLEMENTED ("size of mapping table");
}
// using default ctor and copy operations
bool
empty() const
{
return 0 == size();
}
size_t size() const { return table_.size(); }
bool empty() const { return 0 == size(); }
void clear() { table_.clear(); }
void
clear()
{
UNIMPLEMENTED ("purge mapping table");
}
/**
* @internal transient resolution wrapper to be exposed by map-style access.
* A Resolver instance represents an output mapping result, yet to be fully resolved.
* It is created on the stack by the OutputMapping container and internally wired
* back to the container and the actually stored value (pipe-ID-hash) in the table.
* Actually retrieving the result value by the client code triggers invocation
* of the specific resolution functor, embedded in the definition context DEF,
* which was given when instantiating the OutputMapping template.
*/
class Resolver
: public lib::BoolCheckable<Resolver
, boost::equality_comparable<Resolver, Target,
boost::equality_comparable<Resolver>
, boost::noncopyable> >
> >
{
public:
Resolver () { }
OutputMapping& thisMapping_;
HashVal& pID_;
Resolver (OutputMapping& container, HashVal& resultVal)
: thisMapping_(container)
, pID_(resultVal)
{ }
friend class OutputMapping;
/* copy by clients prohibited */
Resolver& operator= (Resolver const&);
Target
resolve() const
{
REQUIRE (pID_);
PId targetPipeID (pID_);
return thisMapping_.resolve (targetPipeID);
}
public:
void
operator= (PId newId2map)
{
UNIMPLEMENTED ("store new fixed mapping");
pID_ = newId2map;
}
void
operator= (PPipe newPipe2map)
{
UNIMPLEMENTED ("store new fixed mapping");
REQUIRE (newPipe2map);
pID_ = newPipe2map->getID();
}
operator Target()
{
UNIMPLEMENTED ("invoke output mapping functor, maybe issue defaults query");
return resolve();
}
bool
isValid() const
{
UNIMPLEMENTED ("is this a NULL object, or a valid stored mapping?");
return bool(pID_);
}
@ -145,33 +181,56 @@ namespace mobject {
friend bool
operator== (Resolver const& a, Resolver const& b)
{
UNIMPLEMENTED ("compare two resolution wrappers");
}
return a.pID_ == b.pID_;
} // note: Resolver depends on tempate parameter DEF
// All instances of DEF are considered equivalent!
friend bool
operator== (Resolver const& rr, Target const& tval)
{
UNIMPLEMENTED ("compare this resolution to given other target value");
return rr.resolve() == tval;
}
};
Resolver&
operator[] (PId)
Resolver
operator[] (PId sourcePipeID)
{
UNIMPLEMENTED ("standard lookup");
if (!contains (table_, sourcePipeID))
{
UNIMPLEMENTED ("how to resolve");
}
return buildResolutionWrapper (sourcePipeID);
}
Resolver&
Resolver
operator[] (PPipe const& pipe)
{
REQUIRE (pipe);
return (*this) [pipe->getID()];
}
Resolver&
Resolver
operator[] (Query<asset::Pipe> const& query4pipe)
{
UNIMPLEMENTED ("lookup by extended query");
HashVal hash4query;
HashVal resulting_targetPipeID;
table_[hash4query] = resulting_targetPipeID;
return buildResolutionWrapper (hash4query);
}
private:
Target
resolve (PId resultingPipeID)
{
return DEF::output(resultingPipeID);
}
Resolver
buildResolutionWrapper (HashVal tableSlot)
{
ASSERT (contains (table_, tableSlot));
return Resolver (*this, table_[tableSlot]);
}
};

View file

@ -1000,16 +1000,16 @@ config.macros.timeline.handler = function(place,macroName,params,wikifier,paramS
}
//}}}</pre>
</div>
<div title="BindingMO" modifier="Ichthyostega" modified="201011220258" created="200905210144" tags="def design discuss Model SessionLogic" changecount="30">
<div title="BindingMO" modifier="Ichthyostega" modified="201011252205" created="200905210144" tags="def design discuss Model SessionLogic" changecount="33">
<pre>Binding-~MObjects are used to associate two entities within the high-level model.
More specifically, such a binding serves
* to outfit any top-level [[Timeline]] with real content, which is contained within a [[Sequence]]
* to build a VirtualClip, that is to link a complete sequence into another sequence, where it appears like a new virtual media or clip.
!Properties of a Binding
Binding is a relation entity, maintaining a link between parts of the session. Actually this link is achieved somewhat indirect: The binding itself is an MObject, but it points to a [[sequence asset|Sequence]]. Moreover, in case of the (top-level) timelines, there is a timeline asset acting frontend for the ~BindingMO.
Binding is a relation entity, maintaining a link between parts of the session. Actually this link is achieved somewhat indirect: The binding itself is an MObject, but it points to a [[sequence asset|Sequence]]. Moreover, in case of the (top-level) timelines, there is a timeline asset acting as a frontend for the ~BindingMO.
* the binding exposes special functions needed to implement the timeline {{red{planned as of 11/10}}}
* similarly, the binding exposes functions allowing to stand-in for a regular clip (when acting as VirtualClip).
* similarly, the binding exposes functions allowing to wrap up the bound sequence as VirtualMedia (when acting as VirtualClip).
* the Binding holds an OutputMapping -- allowing to specify, resolve and remember [[output designations|OutputDesignation]]
Note: there are other binding-like entities within the model, which are deliberately not subsumed below this specification, but rather implemented stand alone.
@ -1025,7 +1025,7 @@ Binding can be considered an implementation object, rarely to be created directl
!!!channel / output mapping {{red{WIP 11/10}}}
The Binding-~MObject stores an OutputMapping. Basically this, together with OutputDesignation, implements the mapping behaviour
* during the build process, output designation(s) are to be retrieved for each pipe.
* during the build process, output designation(s) will be retrieved for each pipe.
* indirect and relative designations are to resolved; the relative ones are forwarded to the next enclosing binding
* in any case, the result is an direct WiringPlug, which can then be matched up and wired
* but in case of implementing a virtual clip, in addition to the direct wiring...
@ -3012,7 +3012,7 @@ Any external output sink is managed as a [[slot|DisplayerSlot]] in the ~OutputMa
&amp;rarr; see also the PlayerDummy
</pre>
</div>
<div title="OutputMapping" modifier="Ichthyostega" modified="201011230136" created="201011080238" tags="Model spec draft" changecount="22">
<div title="OutputMapping" modifier="Ichthyostega" modified="201011270311" created="201011080238" tags="Model spec draft" changecount="23">
<pre>An output mapping serves to //resolve//&amp;nbsp; [[output designations|OutputDesignation]].
!Mapping situations
@ -3041,7 +3041,7 @@ All these mapping steps are listed here, because they exhibit a common pattern.
!Implementation notes
Thus the mapping is a copyable value object, based on a associative array. It may be attached to a model object and persisted alongside. The mapping is assumed to run a defaults query when necessary. To allow for that, it should be configured with a query template (string). Frequently, special //default pipe// markers will be used at places, where no distinct pipe-ID is explicitly specified. Besides that, invocations might supply additional predicates (e.g. {{{ord(2)}}} to denote &quot;the second stream of this kind&quot;) to hint the defaults resolution. Moreover, the mapping needs a way to retrieve the set of possible results, allowing to filter the results of the rules based default. Mappings might be defined explicitly. Instead of storing a //bottom value,// an {{{isDefined()}}} predicate might be preferable.
First and foremost, mapping can be seen as a //functional abstraction.// As it's used at implementation level, encapsulation of detail types in't the primary concern, so it's a candidate for generic programming. But there //is// a concern better to be concealed at the usage site, namely accessing the rules system. Thus mapping leads itself to the frequently used implementation pattern where there is a generic frontend as header, calling into opaque functions embedded within a separate compilation unit.
First and foremost, mapping can be seen as a //functional abstraction.// As it's used at implementation level, encapsulation of detail types in't the primary concern, so it's a candidate for generic programming: For each of those use cases outlined above, a distinct mapping type is created by instantiating the {{{OutputMapping&lt;DEF&gt;}}} template with a specifically tailored definition context ({{{DEF}}}), which takes on the role of a strategy. Individual instances of this concrete mapping type may be default created and copied freely. This instantiation process includes picking up the concrete result type and building a functor object for resolving on the fly. Thus, in the way typical for generic programming, the more involved special details are moved out of sight, while being still in scope for the purpose of inlining. But there //is// a concern better to be encapsulated and concealed at the usage site, namely accessing the rules system. Thus mapping leads itself to the frequently used implementation pattern where there is a generic frontend as header, calling into opaque functions embedded within a separate compilation unit.
</pre>
</div>
<div title="Overview" modifier="Ichthyostega" modified="200906071810" created="200706190300" tags="overview img" changecount="13">