MobjectRef_test passes compiler as a whole

This commit is contained in:
Fischlurch 2010-01-13 05:57:14 +01:00
parent 71428ccf6f
commit 26972376de
3 changed files with 89 additions and 31 deletions

View file

@ -48,6 +48,7 @@ namespace mobject {
LUMIERA_ERROR_DEFINE (INVALID_PLACEMENTREF, "unresolvable placement reference, or of incompatible type");
LUMIERA_ERROR_DEFINE (BOTTOM_PLACEMENTREF, "NIL placement-ID marker encountered.");
LUMIERA_ERROR_DEFINE (BOTTOM_MOBJECTREF, "NIL MObjectRef encountered");

View file

@ -22,9 +22,30 @@
/** @file mobject-ref.hpp
** A reference handle pointing at an MObject, attached (placed) to the session.
** Allows client code to access both the object and the placement, even from a
** separate Layer or from within plugin code.
** External MObject/Placement reference.
** This smart-handle referres to an MObject, attached (placed) into the session.
** It is a copyable value object, implemented by an LUID (hash) and an shared_ptr.
** Holding an MObject ref keeps the referred MObject alive, but gives no guarantees
** regarding the validity of the referred \em Placement within the session. On each
** access, the placement is re-fetched using the PlacementIndex, which may fail.
**
** MObjectRef allows to access the pointee (MObject subclass) by using the dereferentiation
** operator, and it allows to access the Placement within the session. Moreover, as an
** convenience shortcut, some of Placement's query operations are directly exposed.
**
** !Lifecycle
** An MObjectRef is always created inactive. It needs to be activated explicitly,
** providing either a direct (language) ref to an Placement within the session,
** or an PlacementRef tag, or another MObjecRef. It can be closed (detached).
**
** !Type handling
** Like any smart-ptr MObjectRef is templated on the actual type of the pointee.
** It can be built or re-assigned from a variety of sources, given the runtime type
** of the referred pointee is compatible to this template parameter type. This
** allows flexibly to re-gain a specifically typed context, even based just
** on a plain LUID. This functionality is implemented by accessing the
** PlacementIndex within the session, and then by using the RTTI of
** the fetched Placement's pointee.
**
** @see MObject
** @see Session
@ -39,24 +60,23 @@
#define MOBJECT_MOBJECT_REF_H
//#include "pre.hpp"
//#include "proc/mobject/session/locatingpin.hpp"
//#include "proc/asset/pipe.hpp"
#include "lib/handle.hpp"
#include "lib/lumitime.hpp"
#include "proc/mobject/placement.hpp"
#include "proc/mobject/placement-ref.hpp"
//#include <tr1/memory>
///////////////////////////////////////////TODO: define an C-API representation here, make the header multilingual!
namespace mobject {
// using std::tr1::shared_ptr;
class MObject;
LUMIERA_ERROR_DECLARE (BOTTOM_MOBJECTREF); ///< NIL MObjectRef encountered
/**
* An active (smart-ptr like) external reference
* to a specifically placed MObject "instance" within the session.
@ -69,29 +89,43 @@ namespace mobject {
class MORef
: public lib::Handle<MO>
{
typedef lib::Handle<MO> _Par;
typedef lib::Handle<MO> _Handle;
PlacementRef<MO> pRef_;
using _Handle::smPtr_;
PlacementRef<MO> pRef_; ////////////////////////////////////////////////////////////////////TODO: how to create an "inactive" PlacementRef???
using _Par::smPtr_;
public:
MO*
operator-> () const
{
REQUIRE (pRef_ && smPtr_, "Lifecycle-Error: not activated");
if (!smPtr_)
throw lumiera::error::State("Lifecycle error: MObject ref not activated"
,LUMIERA_ERROR_BOTTOM_MOBJECTREF);
ENSURE (INSTANCEOF (MO, smPtr_.get()));
return smPtr_.operator-> ();
}
Placement<MO>& getPlacement() const
{
REQUIRE (pRef_ && smPtr_, "Lifecycle-Error: not activated");
ENSURE (INSTANCEOF (MO, smPtr_.get()));
return *pRef_;
}
/** resolves the referred placement to an
* ExplicitPlacement and returns the found start time
*/
lumiera::Time const&
getStartTime()
{
return pRef_.resolve().time;
}
/* === Lifecycle === */
@ -119,7 +153,7 @@ namespace mobject {
* - a plain LUID
* @throws error::Invalid when the (directly or indirectly
* referred placement isn't known to the session PlacementIndex,
* or when the placement actually found has an incompatible dynamic type
* or when the placement actually found has an incompatible dynamic type
*/
template<typename REF>
MORef&
@ -153,16 +187,46 @@ namespace mobject {
return activate (oRef.getPlacement().getID());
}
/** cross assignment.
* @note besides that, we use the default generated copy operations.
* @note STRONG exception safety guarantee
* @throws error::Invalid when the referred placement isn't registered
* within the current session, or if the runtime type of the pointees
* aren't assignment compatible
*/
template<typename MOX>
MORef&
operator= (MORef<MOX> const& oRef)
{
return activate (oRef);
}
/* == diagnostics == */
bool
isValid() const
{
return pRef_.isValid();
}
size_t
use_count() const
{
return pRef_.use_count();
}
template<class MOX>
bool
isCompatible() const
{
return pRef_
&& (*pRef_).isCompatible<MOX>();
}
/* == equality comparisons == */
@ -221,7 +285,6 @@ namespace mobject {
}
};
////////////////TODO currently just fleshing out the API....
typedef MORef<MObject> MObjectRef;

View file

@ -52,7 +52,7 @@ namespace test {
using session::SessionServiceMockIndex;
using session::PPIdx;
/***************************************************************************
* @test properties and behaviour of the external reference-mechanism for
@ -116,7 +116,6 @@ namespace test {
PlacementRef<MObject> ref2 (pClip2);
#if false //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 384 !!!!!!!!!
// -----Tests------------------
checkBuildMObjectRef (rP1, &pClip1);
checkBuildMObjectRef (rP2, &pClip2);
@ -131,7 +130,6 @@ namespace test {
checkLifecycle (rP1,rP2);
checkTypeHandling (luid);
// -----Tests------------------
#endif ////////////////////////////////////////////////////////////////////////////////////////TODO lots of things unimplemented.....!!!!!
// verify clean state
index->remove (pClip1);
@ -168,30 +166,28 @@ namespace test {
// access the Placement-API
ASSERT (3 == rMO.use_count()); // now rMO shares ownership with the Placement
#if false //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 384 !!!!!!!!!
ASSERT (0 < rMO.getStartTime()); // (internally, this resolves to an ExplicitPlacement) /////////TICKET #332
ASSERT (Time(0) < rMO.getStartTime()); // (internally, this resolves to an ExplicitPlacement) /////////TICKET #332
ASSERT ( rMO.isCompatible<MObject>());
ASSERT ( rMO.isCompatible<Clip>());
ASSERT (!rMO.isCompatible<TestSubMO1>());
Time start = rMO.getStartTime();
#endif ////////////////////////////////////////////////////////////////////////////////////////TODO lots of things unimplemented.....!!!!!
// re-link to the Placement (note we get the Clip API!)
Placement<Clip> & refP = rMO.getPlacement();
ASSERT (refP);
ASSERT (refP.isValid());
ASSERT (3 == refP.use_count());
ASSERT (&refP == placementAdr); // actually denotes the address of the original Placement in the "session"
cout << string(refP) << endl;
ExplicitPlacement exPla = refP.resolve();
// ASSERT (exPla.time == start); // recovered Placement resolves to the same time as provided by the proxied API
ASSERT (exPla.time == start); // recovered Placement resolves to the same time as provided by the proxied API
ASSERT (4 == refP.use_count()); // but now we've indeed created an additional owner (exPla)
ASSERT (4 == rMO.use_count());
}
void
checkComparison (PMO& p1, PMO& p2)
checkComparison (PMO const& p1, PMO const& p2)
{
PlacementRef<Clip> pRef1 (p1);
PlacementRef<MObject> pRef2 (p2);
@ -258,7 +254,7 @@ namespace test {
void
checkLifecylce (PMObj const& p1, PMObj const& p2)
checkLifecycle (PMObj const& p1, PMObj const& p2)
{
ASSERT (2 == p1.use_count());
ASSERT (2 == p2.use_count());
@ -290,7 +286,7 @@ namespace test {
ASSERT (2 == p2.use_count());
VERIFY_ERROR (INVALID_PLACEMENTREF, rMO.getPlacement() );
// VERIFY_ERROR (INVALID_MOBJECTREF, rMO->getMedia() );
VERIFY_ERROR (BOTTOM_MOBJECTREF, rMO->getMedia() );
}
void
@ -316,9 +312,7 @@ namespace test {
// impossible, because Clip isn't a subclass of TestSubMO1:
VERIFY_ERROR (INVALID_PLACEMENTREF, rSub1.activate(luid) );
#if false //////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET 384 !!!!!!!!!
// VERIFY_ERROR (INVALID_PLACEMENTREF, rSub1 = rMObj );
#endif ////////////////////////////////////////////////////////////////////////////////////////TODO lots of things unimplemented.....!!!!!
VERIFY_ERROR (INVALID_PLACEMENTREF, rSub1 = rMObj );
ASSERT (rMObj->isValid());
ASSERT (rClip->isValid());
@ -327,12 +321,12 @@ namespace test {
// doesn't compile, because the function isn't on MObject API:
// rMObj->getMedia();
// can assign, because the actual type is relevant:
rClip.close();
ASSERT (3 == rMObj.use_count());
ASSERT (0 == rClip.use_count());
// rClip = rMObj;
// can assign, because the actual type checked:
rClip = rMObj;
ASSERT (4 == rMObj.use_count());
ASSERT (4 == rClip.use_count());