finished reworking Placement (hierarchy and ID)

This commit is contained in:
Fischlurch 2009-05-31 05:02:03 +02:00
parent e8c25fca0a
commit d49eea6e5d
10 changed files with 140 additions and 70 deletions

View file

@ -26,6 +26,7 @@
#include "proc/mobject/mobject.hpp"
#include <boost/format.hpp>
#include <typeinfo>
using boost::format;
using boost::str;

View file

@ -132,7 +132,7 @@ namespace mobject {
* which is subject to placement.
* @note we don't provide operator*
*/
virtual MObject *
MObject *
operator-> () const
{
ENSURE (*this);
@ -193,7 +193,7 @@ namespace mobject {
friend class session::MObjectFactory;
public:
virtual MO*
MO*
operator-> () const
{
ENSURE (INSTANCEOF (MO, this->get()));

View file

@ -29,7 +29,19 @@ PLANNED "PlacementBasic_test" PlacementBasic_test <<END
END
PLANNED "PlacementHierarchy_test" PlacementHierarchy_test <<END
TEST "hierarchical placement types" PlacementHierarchy_test <<END
out: sizeof\( \w+ \) = \d{2}
out: Placement.+mobject.+test.+TestSubMO1.+. use-cnt=1 .*
out: Placement.+mobject.+test.+TestSubMO2.+. use-cnt=1 .*
out: Placement.+mobject.+test.+TestSubMO21.+ use-cnt=2 .*
out: Placement.+mobject.+test.+TestSubMO21.+ use-cnt=2 .*
out: Placement.+mobject.+session.+Clip.+.... use-cnt=2 .*
out: TestSubMO1\(ID= \d{3}\)
out: TestSubMO2\(ID= \d{3}\)
out: TestSubMO21\(ID= \d{3}\)
out: specialAPI()
out: specialAPI()
out: pID\(\w{16}\)
END

View file

@ -121,7 +121,7 @@ namespace asset
ASSERT (c1 == c2);
PPipe pipe3 = Pipe::query ("pipe("+pID2+")");
//////////////////////////////////////////////////////////////TODO: er macht eine Neue, anstatt die Bestehende zu finden
//////////////////////////////////////////////////////////////TODO: that's broken; creating a new one instead to find the existing one, as it should be
ASSERT (pipe3 == pipe2);
}

View file

@ -33,10 +33,8 @@ using util::isnil;
namespace asset
{
namespace test
{
namespace asset{
namespace test {
@ -59,7 +57,7 @@ namespace asset
typedef TestAsset<Asset> TA;
typedef TA::PA PTestA;
/** @test check operation of basic asset dependency support
*/
@ -149,12 +147,12 @@ namespace asset
a2->enable(true);
ASSERT (a1->isActive());
ASSERT (a2->isActive());
a3->enable(false);
ASSERT (a1->isActive());
ASSERT (a2->isActive());
ASSERT (!a3->isActive()); // no dependency...
a1->enable(false);
a3->enable();
ASSERT (!a1->isActive());
@ -210,6 +208,4 @@ namespace asset
} // namespace test
} // namespace asset
}} // namespace asset::test

View file

@ -79,7 +79,7 @@ namespace mobject {
ExplicitPlacement expla = pc.resolve();
ASSERT (expla.time == 1);
ASSERT (!expla.chain.isOverdetermined());
//ASSERT (*expla == *pc); ////////////////////////TODO: define equality on placements
//ASSERT (*expla == *pc); ////////////////////////TODO: define equality on placements (Trac #119)
// now overconstraining with another Placement
pc.chain(Time(2));

View file

@ -1,5 +1,5 @@
/*
PlacementHierarchy(Test) - concept draft how to deal with the MObject hierarchy in Placements
PlacementHierarchy(Test) - cooperating hierarchical placement types
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
@ -22,47 +22,40 @@
#include "lib/test/run.hpp"
//#include "proc/asset/media.hpp"
//#include "proc/mobject/session.hpp"
//#include "proc/mobject/session/edl.hpp"
//#include "proc/mobject/session/testclip.hpp"
//#include "proc/mobject/placement.hpp"
//#include "proc/mobject/placement-ref.hpp"
//#include "proc/mobject/explicitplacement.hpp"
#include "lib/test/test-helper.hpp"
#include "proc/mobject/test-dummy-mobject.hpp"
#include "lib/hash-indexed.hpp"
#include "proc/mobject/session/clip.hpp"
#include "proc/mobject/placement.hpp"
#include "proc/asset/media.hpp"
#include "lib/util.hpp"
#include <boost/format.hpp>
#include <tr1/memory>
#include <iostream>
#include <cstdlib>
using lib::HashIndexed;
using std::tr1::shared_ptr;
using boost::format;
using boost::str;
//using lumiera::Time;
//using util::contains;
using lib::HashIndexed;
using std::string;
using std::cout;
using std::rand;
using std::endl;
namespace mobject {
namespace session {
namespace test {
using session::Clip;
using lib::test::showSizeof;
using namespace mobject::test;
/*******************************************************************************
* @test Currently (5/09) this is a concept draft separate of any existing types.
* The intention is to rework the Placement implementation based on the
* outcomes of this experiment. When doing so, this test could later on
* serve to document and cover the corresponding Placement properties.
/***************************************************************************************
* @test creating placements specifically typed, forming an hierarchy of placement types
* which loosely mirrors the hierarchy of the pointee types. Assignments between
* placement of differing type, while still sharing ownership.
* @see mobject::Placement
* @see mobject::MObject#create
* @see lib::hash::HashIndexed
*/
class PlacementHierarchy_test : public Test
{
@ -70,32 +63,99 @@ namespace test {
virtual void
run (Arg)
{
TestPlacement<TestSubMO1> pSub1(*new TestSubMO1);
TestPlacement<TestSubMO2> pSub2(*new TestSubMO2);
TestPlacement<TestSubMO21> pSub3(*new TestSubMO21);
typedef Placement<MObject> PMObj;
typedef TestPlacement<> PDummy;
typedef TestPlacement<TestSubMO1> PSub1;
typedef TestPlacement<TestSubMO2> PSub2;
typedef TestPlacement<TestSubMO21,TestSubMO2> PSub21;
TestPlacement<DummyMO> pSubM (pSub3);
PSub1 pSub1(*new TestSubMO1);
PSub2 pSub2(*new TestSubMO2);
PSub21 pSub3(*new TestSubMO21);
/////////////////////////////////TODO
format fmt ("sizeof( %s ) = %d\n");
cout << fmt % "Pla<Sub1>" % sizeof(pSub1);
cout << fmt % "Pla<Sub2>" % sizeof(pSub2);
cout << fmt % "Pla<Sub3>" % sizeof(pSub3);
PDummy pSubM (pSub3);
PMObj pClip = asset::Media::create("test-1", asset::VIDEO)->createClip();
ASSERT (INSTANCEOF (Placement<MObject>, &pSub1));
ASSERT (INSTANCEOF (Placement<MObject>, &pSub2));
ASSERT (INSTANCEOF (Placement<MObject>, &pSub3));
ASSERT (INSTANCEOF (Placement<MObject>, &pSubM));
ASSERT (INSTANCEOF (Placement<DummyMO>, &pSub1));
ASSERT (INSTANCEOF (Placement<DummyMO>, &pSub2));
ASSERT (INSTANCEOF (Placement<DummyMO>, &pSub3));
ASSERT (INSTANCEOF (TestPlacement<DummyMO>, &pSub1));
ASSERT (INSTANCEOF (TestPlacement<DummyMO>, &pSub2));
ASSERT (INSTANCEOF (TestPlacement<DummyMO>, &pSub3));
ASSERT ( INSTANCEOF (TestPlacement<TestSubMO2>, &pSub3));
// the following won't succeed...
// ASSERT (INSTANCEOF (TestPlacement<TestSubMO21>, &pSub2)); // parent not instance of subclass
// ASSERT (INSTANCEOF (TestPlacement<TestSubMO2>, &pSub1)); // separate branch in the hierarchy
cout << showSizeof(pSub1) << endl;
cout << showSizeof(pSub2) << endl;
cout << showSizeof(pSub3) << endl;
cout << showSizeof(pSubM) << endl;
cout << showSizeof(pClip) << endl;
ASSERT (sizeof(pSub1) == sizeof(pSub3));
ASSERT (sizeof(pClip) == sizeof(pSub3));
cout << string(pSub1) << endl;
cout << string(pSub2) << endl;
cout << string(pSub3) << endl;
cout << string(pSubM) << endl;
cout << string(pClip) << endl;
cout << pSub1->operator string() << endl;
cout << pSub2->operator string() << endl;
cout << pSubM->operator string() << endl;
cout << string(pSub1) << "\n";
cout << string(pSub2) << "\n";
cout << string(pSubM) << "\n";
cout << pSub1->operator string() << "\n";
cout << pSub2->operator string() << "\n";
cout << pSubM->operator string() << "\n";
pSub3->specialAPI();
cout << format_PlacementID(pSub1) << "\n";
cout << format_PlacementID(pSub2) << "\n";
cout << format_PlacementID(pSub3) << "\n";
cout << format_PlacementID(pSubM) << "\n";
ASSERT (2 == pSubM.use_count());
ASSERT (2 == pSub3.use_count());
pClip = pSubM; // slicing and shared ownership
ASSERT (3 == pSubM.use_count());
ASSERT (3 == pSub3.use_count());
ASSERT (3 == pClip.use_count());
cout << "Hurgha!\n";
// now do a brute-force re-interpretation
// note this is still protected by an ASSERT on the operator->()
PSub21& hijacked = reinterpret_cast<PSub21&> (pClip);
hijacked->specialAPI();
ASSERT (3 == hijacked.use_count());
ASSERT (hijacked.getID() == pSub3.getID());
cout << format_PlacementID(pSub1) << endl;
cout << format_PlacementID(pSub2) << endl;
cout << format_PlacementID(pSub3) << endl;
cout << format_PlacementID(pSubM) << endl;
cout << format_PlacementID(pClip) << endl;
pClip = pSub1;
ASSERT (2 == pSubM.use_count());
ASSERT (2 == pSub3.use_count());
ASSERT (2 == pClip.use_count());
ASSERT (2 == pSub1.use_count());
///////////////////////////////////////////////////////////////////////////////TODO: find a way to configure NoBug to throw in case of assertion
///////////////////////////////////////////////////////////////////////////////TODO: configure NoBug specifically for the testsuite
// try
// {
// hijacked->specialAPI();
// NOTREACHED;
// }
// catch (...)
// {
// ASSERT (lumiera_error () == error::LUMIERA_ERROR_ASSERTION);
// }
}
};

View file

@ -116,7 +116,7 @@ namespace test {
struct TestSubMO21 : TestSubMO2
{
virtual operator string() const { return display("TestSubMO21"); }
void specialAPI() { cout << "specialAPI()\n";}
virtual void specialAPI() const { cout << "specialAPI()\n";}
};
@ -141,7 +141,7 @@ namespace test {
: TestPlacement<B>(dummyObj)
{ }
virtual DMO*
DMO *
operator-> () const
{
ENSURE (INSTANCEOF (DMO, this->get()));

View file

@ -76,12 +76,12 @@ namespace test{
ASSERT (2 == sizeof (rmpf2));
ASSERT (3 == sizeof (rmpf3));
cout << showSizeof((size_t)42,"theUniverse") << endl;
cout << showSizeof<char>("just a char") << endl;
cout << showSizeof(murpf) << endl;
cout << showSizeof(rmpf1) << endl;
cout << showSizeof(rmpf2) << endl;
cout << showSizeof<Wrmpf3>() << endl;
cout << showSizeof((size_t)42, "theUniverse") << endl;
cout << showSizeof<char>("just a char") << endl;
cout << showSizeof(murpf) << endl;
cout << showSizeof(rmpf1) << endl;
cout << showSizeof(rmpf2) << endl;
cout << showSizeof<Wrmpf3>() << endl;
Wrmpf1 *p1 = &rmpf1;
Wrmpf1 *p2 = 0;

View file

@ -579,7 +579,7 @@ For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from
<div title="AssetManager" modifier="Ichthyostega" created="200709200300" changecount="1">
<pre>The Asset Manager provides an Interface to some internal Database holding all Assets in the current Session and System state. It may be a real Database at some point (and for the moment it's a Hashtable). Each [[Asset]] is registered automatically with the Asset Manager; it can be queried either by it's //identification tuple// or by it's unique ID.</pre>
</div>
<div title="AttachedPlacementProblem" modifier="Ichthyostega" modified="200905120332" created="200801111305" tags="SessionLogic impl draft dynamic" changecount="14">
<div title="AttachedPlacementProblem" modifier="Ichthyostega" modified="200905292133" created="200801111305" tags="SessionLogic impl draft dynamic" changecount="15">
<pre>Placing an MObject relatively to another object such that it should be handled as //attached//&amp;nbsp; to the latter results in several design and implementation challenges. Actually, such an attachment creates a cluster of objects. The typical use case is that of an effect attached to a clip or processing pipe.
* attachment is not a globally fixed relation between objects, rather, it typically exists only for some limited time span (e.g. the duration of the basic clip the effect is attached to)
* the order of attachment is important and the attached placement may create a fork in the signal flow, so we need a way for specifying reproducibly how the resulting wiring should be
@ -592,7 +592,7 @@ The first step towards an solution is to isolate the problem; obviously we don't
!!Implementation notes
Attachment is managed within the participating placements, mostly by special [[locating pins|LocatingPin]]. Attachment doesn't necessarily nail down an attached object to a specific position, rather the behaviour depends on the type of the object and the locating pins actually involved, especially on their order and priority. For example, if an {{{Placement&lt;Effect&gt;}}} doesn't contain any locating pin defining a temporal position, then the attachment will result in the placement inheriting the temporal placement of the //attachment head// (i.e. the clip this effect has been attached to). But, if on the contrary the effect in question //does// have an additional locating pin, for example relative to another object or even to a fixed time position, this one will &quot;win&quot; and determine the start position of the effect &amp;mdash; it may even move the effect out of the time interval covered by the clip, in which case the attachment has no effect on the clip's processing pipe.
The attachment relation is hierarchical and has a clearly defined //active// and //passive// side: The attachment head is the parent node in a tree, but plays the role of the passive partner, to which the child nodes attach. But note, this does not mean we are limited to a single attachment head. Actually, each placement has a list of locating pins and thus can attach to several other placements. For example, a transition attaches to at least two local pipes (clips).
The attachment relation is hierarchical and has a clearly defined //active// and //passive// side: The attachment head is the parent node in a tree, but plays the role of the passive partner, to which the child nodes attach. But note, this does not mean we are limited to a single attachment head. Actually, each placement has a list of locating pins and thus can attach to several other placements. For example, a transition attaches to at least two local pipes (clips). {{red{TODO: unresolved design problem; seems to contradict the PlacementScope}}}
!!!!Relation to memory management
Attachment on itself does //not// keep an object alive. Rather, it's a direct reference and has to be taken into account when deleting an object. On the other hand, processing nodes in the render engine never depend on placements &amp;mdsash; they always refer directly to the MObject instance or even the underlying asset. In the case of MObject instances, the pointer from within the engine will //share ownership// with the placement (remember: both are derived from {{{boost::shared_ptr}}}).
@ -2969,7 +2969,7 @@ We need a way of addressing existing [[pipes|Pipe]]. Besides, as the Pipes and T
&lt;&lt;tasksum end&gt;&gt;
</pre>
</div>
<div title="PlanningSessionInMem" modifier="Ichthyostega" modified="200905291920" created="200904252258" tags="impl SessionLogic draft" changecount="16">
<div title="PlanningSessionInMem" modifier="Ichthyostega" modified="200905310301" created="200904252258" tags="impl SessionLogic draft" changecount="19">
<pre>//This page is a scrapbook for working out the implementation of the [[Session Datastructure in Memory|SessionDataMem]]//
This is a difficult untertaking, because there are several dependencies (most of which aren't fully designed yet as of 5/09)
* the GUI uses an adapted version of the HighLevelModel; these datastructures are intended to be backed by the Session
@ -2993,8 +2993,9 @@ This is a difficult untertaking, because there are several dependencies (most of
&lt;&lt;task &gt;&gt; specify the editing operations
!Interface
&lt;&lt;task&gt;&gt;evaluate models for the [[reference problem|MObjectRef]]
&lt;&lt;task 2 3 3&gt;&gt; implement an hash-ID to be incorporated into placements
&lt;&lt;task 1 1 1&gt;&gt; evaluate models for the [[reference problem|MObjectRef]]
&lt;&lt;task 2 3 3&gt;&gt; implement an hash-ID
&lt;&lt;task 1 2 2&gt;&gt; incorporate this ID into class Placement
&lt;&lt;task 1 1 0&gt;&gt; implement PlacementRef
&lt;&lt;task 2 2 0&gt;&gt; implement MObjectRef