PlacementIndex implemented, unit test pass

This commit is contained in:
Fischlurch 2010-01-09 05:10:32 +01:00
parent 96f19c656d
commit 14c7f7fc62
7 changed files with 82 additions and 69 deletions

View file

@ -78,7 +78,7 @@ namespace asset
/** use another wiring template. Triggers complete rebuild of the render engine. */
void switchProcPatt (PProcPatt& another);
/** convienience shortcut for retrieving default configured pipes */
/** convenience shortcut for retrieving default configured pipes */
static PPipe query (string properties) ;
};

View file

@ -34,7 +34,7 @@
**
** @todo this can be considered a preliminary sketch without being backed
** by actual functionality. Just enough to be able to drive the design of
** other parts ahead. See esp. Trac #100, which contains an idea for a
** other parts ahead. See esp. TICKET #100, which contains an idea for a
** refactoring.
**
*/

View file

@ -23,9 +23,9 @@
/** @file placement-index.cpp
** Implementation of core session storage structure.
** The PlacementIndex associates IDs to instances, and nested scope structure.
** The PlacementIndex associates IDs to instances, within a nested scope structure.
** Moreover, it provides and manages the actual Placement instances (storage),
** considered to be part of the session.
** considered to be part of the session.
**
** Simple hash based implementation. Seems adequate for now (12/09).
** A main table associates Placement-ID to an Placement \em instance, which is contained
@ -34,15 +34,15 @@
** by wrapping up an STL iterator range into a "Lumiera Forward Iterator" (adapter).
** Generally speaking, PlacementIndex is an implementation level facility and provides
** the basic/low-level functionality. For example, the PlacementIndexQueryResolver
** provides depth-first exploration of all the contents of an scope, including nested scopes,
** building on top of these scope iterators from PlacementIndex.
** provides depth-first exploration of all the contents of an scope, including
** nested scopes, building on top of the scope iterators from PlacementIndex.
**
** PlacementIndex can be seen as the core datastructure of the session. Objects are attached
** to the session by adding (copying) a Placement instance, which is owned and managed by
** the PlacementIndex. Adding this Placement instance creates a new Placement-ID, which
** from then on acts as a shorthand for "the object instance" within the session.
** from then on acts as a shorthand for "the object instance" within the session.
** The actual storage is provided by an embedded TypedAllocationManager instance, which
** is planned (as of 12/09) to be backed later by a memory pool based custom allocator.
** is planned (as of 12/09) to be backed later by a memory pool based custom allocator.
**
** @see PlacementRef
** @see PlacementIndex_test
@ -54,29 +54,25 @@
#include "proc/mobject/session/session-impl.hpp"
#include "proc/mobject/session/scope.hpp"
#include "lib/typed-allocation-manager.hpp"
//#include "proc/mobject/mobject.hpp" ///////////////////////TODO necessary?
#include "lib/util-foreach.hpp"
#include "lib/iter-source.hpp"
#include "include/logging.h"
//#include <boost/format.hpp>
//using boost::str;
#include <boost/lambda/lambda.hpp>
#include <boost/functional/hash.hpp>
#include <boost/noncopyable.hpp>
#include <tr1/unordered_map>
#include <tr1/functional>
#include <tr1/memory>
//#include <algorithm>
#include <string>
//#include <map>
namespace mobject {
namespace session {
using boost::hash;
using boost::noncopyable;
using boost::lambda::var;
using std::tr1::shared_ptr;
using std::tr1::unordered_map;
using std::tr1::unordered_multimap;
@ -84,9 +80,6 @@ namespace session {
using std::tr1::placeholders::_1;
using std::tr1::function;
using std::tr1::bind;
//using util::contains;
//using std::string;
//using std::map;
using std::make_pair;
using std::pair;
@ -98,7 +91,7 @@ namespace session {
LUMIERA_ERROR_DEFINE (NOT_IN_SESSION, "referring to a Placement not known to the current session");
LUMIERA_ERROR_DEFINE (PLACEMENT_TYPE, "requested Placement (pointee) type not compatible with data or context");
LUMIERA_ERROR_DEFINE (NONEMPTY_SCOPE, "Placement scope (still) contains other elements");
/* some type shorthands */
@ -107,7 +100,7 @@ namespace session {
typedef PlacementIndex::ID ID;
/**
/*********************************************************************
* Storage and implementation backing the PlacementIndex
* - #placementTab_ is an hashtable mapping IDs to Placement + Scope
* - #scopeTab_ is an reverse association serving to keep track of
@ -139,7 +132,7 @@ namespace session {
PPlacement root_;
public:
Table ()
Table ()
{ }
~Table ()
@ -173,13 +166,14 @@ namespace session {
{
return allocator_.numSlots<PlacementMO>();
}
bool
contains (ID id) const
{
return util::contains(placementTab_, id);
}
PlacementMO&
fetch (ID id) const
{
@ -233,7 +227,6 @@ namespace session {
{
REQUIRE (0 == placementTab_.size());
REQUIRE (0 == scopeTab_.size());
REQUIRE (!root_);
root_ = allocator_.create<PlacementMO> (rootDef);
ID rootID = root_->getID();
@ -257,12 +250,12 @@ namespace session {
/** Store a copy of the given Placement as new instance
* within the index, together with the Scope this Placement
* belongs to.
* within the index, together with the Scope
* this Placement belongs to.
* @note we discard the specific type info.
* It can be rediscovered later with the help
* of the pointee's vtable
* @see Placement#isCompatible
* @see Placement#isCompatible
*/
ID
addEntry (PlacementMO const& newObj, ID scopeID)
@ -308,7 +301,7 @@ namespace session {
typedef lib::IterSource<PID>::iterator IDIter;
PlacementMO* _root_4check () { return root_.get(); }
PlacementMO* _root_4check () { return root_.get(); }
PlacementMO* _element_4check (ID id){ return base_entry(id).element.get();}
PlacementMO* _scope_4check (ID id) { return base_entry(id).scope.get(); }
IDIter _eachEntry_4check () { return eachMapKey (placementTab_); }
@ -323,7 +316,7 @@ namespace session {
{
Slot pos = placementTab_.find (key);
if (pos == placementTab_.end())
throw error::Logic("lost a Placement expected to be registered in the index.");
throw error::Logic("lost a Placement expected to be registered within PlacementIndex.");
return pos->second;
}
@ -385,6 +378,9 @@ namespace session {
}
};
//(End) placement index table implementation
@ -403,8 +399,8 @@ namespace session {
}
PlacementIndex::~PlacementIndex() { }
PlacementMO&
PlacementIndex::getRoot() const
{
@ -433,7 +429,7 @@ namespace session {
__check_knownID(*this,id);
return pTab_->fetch (id);
}
/** retrieve the Scope information
@ -573,13 +569,17 @@ namespace session {
VERIFY ( tab.contains (sco(id)->getID()),
"(1.7) Elements", "Element associated with an unknown scope");
PMO* theElement = elm(id);
PMO& theElement = *elm(id);
ID theScope (sco(id)->getID());
if (theScope == id
&& elm(id)==tab._root_4check()
) // no need to check root,
return; // because root is it's own scope
iterator elementsInScope = tab.queryScopeContents(theScope);
bool properlyRegistered = has_any (elementsInScope, _1_ == *theElement );
bool properlyRegistered = has_any (elementsInScope, _1_ == var(theElement));
VERIFY ( properlyRegistered, "(1.8) Elements", "Element isn't registered as member of the enclosing scope");
VERIFY ( properlyRegistered, "(1.8) Elements", "Element not registered as member of the enclosing scope: "+ theElement);
}
void
@ -624,7 +624,8 @@ namespace session {
/** validity self-check, used for sanity checks and the session self-check.
* The following checks are performed (causing at least one full table scan)
* - root element exists and is valid.

View file

@ -50,7 +50,7 @@
** contained within the PlacementIndex. Usually, the commands expressing any mutating
** operations on the session, bind MObjectRef instances as arguments; similarly, the
** public API functions on the Session interface (and similar facade interfaces) are
** written in terms of MObectRef.
** written in terms of MObectRef.
**
** \par placement scopes
** When adding a Placement to the index, it is mandatory to specify a Scope: this is
@ -91,7 +91,7 @@
** any processing is assumed to happen in a suitable typed context. Consequently,
** client code will never need to fetch Placements directly from the index. This
** allows all type information to be discarded on adding (copying) a Placement
** instances into the PlacementIndex.
** instance into the PlacementIndex.
**
** @note PlacementIndex is <b>not threadsafe</b>.
**
@ -106,8 +106,6 @@
#define MOBJECT_PLACEMENT_INDEX_H
//#include "pre.hpp"
//#include "proc/mobject/session/locatingpin.hpp"
//#include "proc/asset/pipe.hpp"
#include "lib/util.hpp"
#include "lib/error.hpp"
#include "lib/itertools.hpp"
@ -121,7 +119,7 @@
namespace mobject {
class MObject;
namespace session {
@ -220,7 +218,7 @@ namespace session {
/* === forwarding implementations of the templated API === */
namespace { // shortcuts...
template<class MOX>
@ -246,8 +244,8 @@ namespace session {
,LUMIERA_ERROR_NOT_IN_SESSION); ///////////////////////TICKET #197
}
}//(End) shortcuts
template<class MO>

View file

@ -55,7 +55,16 @@ out: pID\(\w{8,16}\)
END
PLANNED "PlacementIndex_test" PlacementIndex_test <<END
TEST "PlacementIndex_test" PlacementIndex_test <<END
out: ^::Placement<.+session.test.TestClip.+ use-cnt=2
out: ^::Placement<.+session.test.TestClip.+ use-cnt=6
out: ^ ::Placement<.+session.test.TestClip.+ use-cnt=6
out: ^ ::Placement<.+session.test.TestClip.+ use-cnt=6
out: ^ ...2 elements at Level 2
out: ^ ::Placement<.+session.test.TestClip.+ use-cnt=6
out: ^ ...3 elements at Level 1
out: ^::Placement<.+session.test.TestClip.+ use-cnt=2
out: ^...3 elements at Level 0
END

View file

@ -132,7 +132,7 @@ namespace test {
hijacked->specialAPI();
ASSERT (3 == hijacked.use_count());
ASSERT (hijacked.getID() == pSub3.getID());
ASSERT (hijacked.getID() == pClip.getID());
cout << format_PlacementID(pSub1) << endl;
cout << format_PlacementID(pSub2) << endl;

View file

@ -23,13 +23,11 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
//#include "proc/asset/media.hpp"
//#include "proc/mobject/session.hpp"
//#include "proc/mobject/session/edl.hpp"
#include "proc/mobject/session/placement-index.hpp"
#include "proc/mobject/session/scope.hpp"
#include "proc/mobject/placement.hpp"
#include "lib/util.hpp"
#include "proc/mobject/session/testclip.hpp"
#include "proc/mobject/session/testroot.hpp"
@ -37,8 +35,6 @@
#include <iostream>
using boost::format;
//using lumiera::Time;
//using util::contains;
using util::isSameObject;
using std::string;
using std::cout;
@ -48,16 +44,15 @@ using std::endl;
namespace mobject {
namespace session {
namespace test {
using asset::VIDEO;
using session::test::TestClip;
typedef PlacementIndex& Idx;
/***************************************************************************
* @test basic behaviour of the index mechanism used to keep track of
* individual Placements as added to the current Session..
* @test basic behaviour of the index mechanism used to keep track
* of individual Placements as added to the current Session.
* @see mobject::Placement
* @see mobject::MObject#create
* @see mobject::Placement#addPlacement
@ -76,14 +71,14 @@ namespace test {
has_size (0, index);
checkSimpleAccess (index);
has_size (1, index);
has_size (2, index);
checkScopeHandling (index);
has_size (7, index);
has_size (8, index);
checkContentsEnumeration (index);
has_size (7, index);
has_size (8, index);
ASSERT (index.isValid());
index.clear();
@ -97,6 +92,7 @@ namespace test {
ASSERT (siz == index.size());
}
void
checkSimpleInsertRemove (Idx index)
{
@ -104,15 +100,17 @@ namespace test {
PMO& root = index.getRoot();
ASSERT (0 == index.size());
ASSERT (!index.contains (clip));
index.insert (clip, root);
PMO::ID elmID = index.insert (clip, root);
ASSERT (1 == index.size());
ASSERT ( index.contains (clip));
ASSERT ( index.contains (elmID));
ASSERT (!index.contains (clip)); // index stores copies
index.remove(clip);
index.remove(clip); // has no effect
ASSERT (1 == index.size());
index.remove(elmID);
ASSERT (0 == index.size());
ASSERT (!index.contains (clip));
ASSERT (!index.contains (elmID));
ASSERT ( index.contains (root));
}
@ -127,13 +125,20 @@ namespace test {
PMO& elm = index.find(elmID);
ASSERT (elmID == elm.getID());
ASSERT (!isSameObject (elm,testObj)); // note: placements are registered as copy
ASSERT (elm == testObj); // they are semantically equivalent
ASSERT (isSameDef(elm,testObj)); // they are semantically equivalent ////////TICKET #511
ASSERT (elmID != testObj.getID()); // but have a distinct identity
PMO::ID elmID2 = index.insert(testObj, root);
ASSERT (elmID != elmID); // ...and each insert creates a new instance
ASSERT (testObj == index.find(elmID2));
ASSERT (elmID2 != elmID); // ...and each insert creates a new instance
ASSERT (testObj != index.find (elmID));
ASSERT (testObj != index.find (elmID2));
ASSERT (isSameDef(testObj, index.find(elmID)));
ASSERT (isSameDef(testObj, index.find(elmID2)));
ASSERT (!isSameObject (testObj, index.find(elmID2)));
ASSERT (!isSameObject (elm, index.find(elmID2)));
// can repeatedly retrieve a reference to the same object
ASSERT ( isSameObject (elm, index.find(elmID )));
ASSERT ( isSameObject (elm, index.find(elmID )));
// can also re-access objects by previous ref
@ -200,7 +205,7 @@ namespace test {
ASSERT (!index.contains(e1331));
ASSERT (!index.remove(e1331));
ASSERT (index.remove(e133)); // but can remove an scope, after emptying it
ASSERT (index.remove(e133)); // but can remove an scope, after emptying it
ASSERT (!index.contains(e133));
}
@ -209,7 +214,7 @@ namespace test {
typedef PlacementIndex::iterator Iter;
/** @test drill down into the tree-like structure
* and enumerate the contents of each element, if any
* and enumerate the contents of each element, if any
*/
void
checkContentsEnumeration (Idx index)
@ -254,6 +259,6 @@ namespace test {
/** Register this test class... */
LAUNCHER (PlacementIndex_test, "unit session");
}}} // namespace mobject::session::test