From d49eea6e5d4e00c9d43cee732ba5febe535aef2d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 31 May 2009 05:02:03 +0200 Subject: [PATCH] finished reworking Placement (hierarchy and ID) --- src/proc/mobject/placement.cpp | 1 + src/proc/mobject/placement.hpp | 4 +- tests/43session.tests | 14 +- tests/components/proc/asset/basicpipetest.cpp | 2 +- .../proc/asset/dependent-assets-test.cpp | 16 +- .../proc/mobject/placement-basic-test.cpp | 2 +- .../proc/mobject/placement-hierarchy-test.cpp | 144 +++++++++++++----- .../proc/mobject/test-dummy-mobject.hpp | 4 +- tests/lib/test/test-helper-test.cpp | 12 +- wiki/renderengine.html | 11 +- 10 files changed, 140 insertions(+), 70 deletions(-) diff --git a/src/proc/mobject/placement.cpp b/src/proc/mobject/placement.cpp index e148694a9..4af940bb4 100644 --- a/src/proc/mobject/placement.cpp +++ b/src/proc/mobject/placement.cpp @@ -26,6 +26,7 @@ #include "proc/mobject/mobject.hpp" #include +#include using boost::format; using boost::str; diff --git a/src/proc/mobject/placement.hpp b/src/proc/mobject/placement.hpp index 49c7005aa..f494d4815 100644 --- a/src/proc/mobject/placement.hpp +++ b/src/proc/mobject/placement.hpp @@ -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())); diff --git a/tests/43session.tests b/tests/43session.tests index 6978f50f0..5b34fbdb2 100644 --- a/tests/43session.tests +++ b/tests/43session.tests @@ -29,7 +29,19 @@ PLANNED "PlacementBasic_test" PlacementBasic_test < 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 diff --git a/tests/components/proc/mobject/placement-basic-test.cpp b/tests/components/proc/mobject/placement-basic-test.cpp index e11968877..637ee4f35 100644 --- a/tests/components/proc/mobject/placement-basic-test.cpp +++ b/tests/components/proc/mobject/placement-basic-test.cpp @@ -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)); diff --git a/tests/components/proc/mobject/placement-hierarchy-test.cpp b/tests/components/proc/mobject/placement-hierarchy-test.cpp index 1064a3f79..d6fd03cab 100644 --- a/tests/components/proc/mobject/placement-hierarchy-test.cpp +++ b/tests/components/proc/mobject/placement-hierarchy-test.cpp @@ -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 @@ -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 #include #include -#include + +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 pSub1(*new TestSubMO1); - TestPlacement pSub2(*new TestSubMO2); - TestPlacement pSub3(*new TestSubMO21); + typedef Placement PMObj; + typedef TestPlacement<> PDummy; + typedef TestPlacement PSub1; + typedef TestPlacement PSub2; + typedef TestPlacement PSub21; - TestPlacement pSubM (pSub3); + PSub1 pSub1(*new TestSubMO1); + PSub2 pSub2(*new TestSubMO2); + PSub21 pSub3(*new TestSubMO21); - /////////////////////////////////TODO - format fmt ("sizeof( %s ) = %d\n"); - cout << fmt % "Pla" % sizeof(pSub1); - cout << fmt % "Pla" % sizeof(pSub2); - cout << fmt % "Pla" % sizeof(pSub3); + PDummy pSubM (pSub3); + + PMObj pClip = asset::Media::create("test-1", asset::VIDEO)->createClip(); + + ASSERT (INSTANCEOF (Placement, &pSub1)); + ASSERT (INSTANCEOF (Placement, &pSub2)); + ASSERT (INSTANCEOF (Placement, &pSub3)); + ASSERT (INSTANCEOF (Placement, &pSubM)); + + ASSERT (INSTANCEOF (Placement, &pSub1)); + ASSERT (INSTANCEOF (Placement, &pSub2)); + ASSERT (INSTANCEOF (Placement, &pSub3)); + + ASSERT (INSTANCEOF (TestPlacement, &pSub1)); + ASSERT (INSTANCEOF (TestPlacement, &pSub2)); + ASSERT (INSTANCEOF (TestPlacement, &pSub3)); + + ASSERT ( INSTANCEOF (TestPlacement, &pSub3)); + + // the following won't succeed... +// ASSERT (INSTANCEOF (TestPlacement, &pSub2)); // parent not instance of subclass +// ASSERT (INSTANCEOF (TestPlacement, &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 (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); +// } } }; diff --git a/tests/components/proc/mobject/test-dummy-mobject.hpp b/tests/components/proc/mobject/test-dummy-mobject.hpp index 8d3e2cd1e..28988c473 100644 --- a/tests/components/proc/mobject/test-dummy-mobject.hpp +++ b/tests/components/proc/mobject/test-dummy-mobject.hpp @@ -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(dummyObj) { } - virtual DMO* + DMO * operator-> () const { ENSURE (INSTANCEOF (DMO, this->get())); diff --git a/tests/lib/test/test-helper-test.cpp b/tests/lib/test/test-helper-test.cpp index c903c523d..032eb3e9b 100644 --- a/tests/lib/test/test-helper-test.cpp +++ b/tests/lib/test/test-helper-test.cpp @@ -76,12 +76,12 @@ namespace test{ ASSERT (2 == sizeof (rmpf2)); ASSERT (3 == sizeof (rmpf3)); - cout << showSizeof((size_t)42,"theUniverse") << endl; - cout << showSizeof("just a char") << endl; - cout << showSizeof(murpf) << endl; - cout << showSizeof(rmpf1) << endl; - cout << showSizeof(rmpf2) << endl; - cout << showSizeof() << endl; + cout << showSizeof((size_t)42, "theUniverse") << endl; + cout << showSizeof("just a char") << endl; + cout << showSizeof(murpf) << endl; + cout << showSizeof(rmpf1) << endl; + cout << showSizeof(rmpf2) << endl; + cout << showSizeof() << endl; Wrmpf1 *p1 = &rmpf1; Wrmpf1 *p2 = 0; diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 9a6c5e54b..f9a017247 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -579,7 +579,7 @@ For every Asset we generate a __Ident tuple__ and a long ID (hash) derived from
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.
-
+
Placing an MObject relatively to another object such that it should be handled as //attached//&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<Effect>}}} 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 "win" and determine the start position of the effect &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 &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
 <<tasksum end>>
 
-
+
//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
 <<task >> specify the editing operations
 
 !Interface
-<<task>>evaluate models for the [[reference problem|MObjectRef]]
-<<task 2 3 3>> implement an hash-ID to be incorporated into placements
+<<task 1 1 1>> evaluate models for the [[reference problem|MObjectRef]]
+<<task 2 3 3>> implement an hash-ID
+<<task 1 2 2>> incorporate this ID into class Placement
 <<task 1 1 0>> implement PlacementRef
 <<task 2 2 0>> implement MObjectRef