From f6cf3195cf53e14c0b68cbb7f31b7231d2c36f55 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 16 Jan 2010 16:34:58 +0100 Subject: [PATCH] * MObjectRef_test pass * This is the integration of some months of work --- src/proc/asset/clip.hpp | 4 +- src/proc/mobject/mobject-ref.hpp | 60 +++++++--- src/proc/mobject/placement-ref.hpp | 22 ++-- tests/43session.tests | 39 +++++- .../proc/mobject/mobject-ref-test.cpp | 111 +++++++++++------- tests/lib/typed-counter-test.cpp | 4 +- 6 files changed, 167 insertions(+), 73 deletions(-) diff --git a/src/proc/asset/clip.hpp b/src/proc/asset/clip.hpp index 53a74faa5..8534b32ba 100644 --- a/src/proc/asset/clip.hpp +++ b/src/proc/asset/clip.hpp @@ -28,6 +28,8 @@ +/////////////////////////TODO: 1/2010 very likely the handling of the clip-asset needs to be rewritten + namespace asset { /** @@ -38,7 +40,7 @@ namespace asset /** media source of this clip */ const Media& source_; - /** the corresponding (dependant) clip-MO */ + /** the corresponding (dependent) clip-MO */ PClipMO clipMO_; public: diff --git a/src/proc/mobject/mobject-ref.hpp b/src/proc/mobject/mobject-ref.hpp index f91c978f2..73c87a861 100644 --- a/src/proc/mobject/mobject-ref.hpp +++ b/src/proc/mobject/mobject-ref.hpp @@ -22,7 +22,7 @@ /** @file mobject-ref.hpp - ** External MObject/Placement reference. + ** 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 @@ -42,10 +42,10 @@ ** 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 + ** 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. + ** the fetched Placement's pointee. ** ** @see MObject ** @see Session @@ -65,6 +65,8 @@ #include "proc/mobject/placement.hpp" #include "proc/mobject/placement-ref.hpp" +#include + ///////////////////////////////////////////TODO: define an C-API representation here, make the header multilingual! @@ -110,12 +112,18 @@ namespace mobject { return smPtr_.operator-> (); } + Placement& getPlacement() const { + if (!isValid()) + throw lumiera::error::State("Accessing inactive MObject ref" + ,LUMIERA_ERROR_BOTTOM_MOBJECTREF); + ENSURE (INSTANCEOF (MO, smPtr_.get())); return *pRef_; } + /** resolves the referred placement to an * ExplicitPlacement and returns the found start time */ @@ -160,12 +168,11 @@ namespace mobject { activate (REF const& pRefID) { PlacementRef newRef (pRefID); - if (newRef.isValid() - && pRef_ != newRef ) - { - return activate (*newRef); // STRONG exception safe - } - else return *this; + + if (isValid() && pRef_ == newRef ) + return *this; // self assignment detected + else + return activate (*newRef); // STRONG exception safe } /** build and activate an MObject reference based on @@ -208,13 +215,14 @@ namespace mobject { bool isValid() const { - return pRef_.isValid(); + return _Handle::isValid() + && pRef_.isValid(); } size_t use_count() const { - return pRef_.use_count(); + return isValid()? pRef_.use_count() : 0; } template @@ -225,6 +233,12 @@ namespace mobject { && (*pRef_).isCompatible(); } + operator string() const ///////////////////////TICKET #527 should be better integrated with the other object types + { + return isValid()? string(getPlacement()) + : "MRef-NIL"; + } + @@ -234,54 +248,62 @@ namespace mobject { bool operator== (MORef const& oRef) const { - return oRef == this->pRef_; + return isValid() + && oRef == this->pRef_; } template bool operator!= (MORef const& oRef) const { - return oRef != this->pRef_; + return !isValid() + || oRef != this->pRef_; } template friend bool operator== (MORef const& oRef, PlacementRef const& pRef) { - return oRef.pRef_ == pRef; + return oRef.isValid() + && oRef.pRef_ == pRef; } template friend bool operator!= (MORef const& oRef, PlacementRef const& pRef) { - return oRef.pRef_ != pRef; + return !oRef.isValid() + || oRef.pRef_ != pRef; } template friend bool operator== (PlacementRef const& pRef, MORef const& oRef) { - return pRef == oRef.pRef_; + return oRef.isValid() + && pRef == oRef.pRef_; } template friend bool operator!= (PlacementRef const& pRef, MORef const& oRef) { - return pRef != oRef.pRef_; + return !oRef.isValid() + || pRef != oRef.pRef_; } bool operator== (PlacementMO::ID const& pID) const { - return PlacementMO::ID (pRef_) == pID; + return isValid() + && PlacementMO::ID (pRef_) == pID; } bool operator!= (PlacementMO::ID const& pID) const { - return PlacementMO::ID (pRef_) != pID; + return !isValid() + || PlacementMO::ID (pRef_) != pID; } }; diff --git a/src/proc/mobject/placement-ref.hpp b/src/proc/mobject/placement-ref.hpp index a354a2897..ac4273a26 100644 --- a/src/proc/mobject/placement-ref.hpp +++ b/src/proc/mobject/placement-ref.hpp @@ -232,12 +232,8 @@ namespace mobject { static void validate (_Id const& rId) { - PlacementMX& pRef (access (rId)); - if (!(pRef.template isCompatible())) - throw lumiera::error::Invalid("actual type of the resolved placement is incompatible",LUMIERA_ERROR_INVALID_PLACEMENTREF); - - ////////////////////////TODO: 1. better message, including type? - ////////////////////////TODO: 2. define a separate error-ID for the type mismatch! + access (rId); // may throw + /////////////////////////////TODO more to check on each PlacementRef creation? } static _Id const& @@ -267,10 +263,16 @@ namespace mobject { throw lumiera::error::Logic ("Attempt to access a NIL PlacementRef" ,LUMIERA_ERROR_BOTTOM_PLACEMENTREF); - Placement & pla (session::SessionServiceFetch::resolveID (placementID)); // may throw - REQUIRE (pla.isValid()); - ASSERT (pla.isCompatible()); - return static_cast (pla); + Placement & genericPlacement (session::SessionServiceFetch::resolveID (placementID)); // may throw + REQUIRE (genericPlacement.isValid()); + + if (!(genericPlacement.template isCompatible())) + throw lumiera::error::Invalid("actual type of the resolved placement is incompatible" + , LUMIERA_ERROR_INVALID_PLACEMENTREF); + ////////////////////////TODO: 1. better message, including type? + ////////////////////////TODO: 2. define a separate error-ID for the type mismatch! + + return static_cast (genericPlacement); } }; diff --git a/tests/43session.tests b/tests/43session.tests index f9f87cc45..77dc68817 100644 --- a/tests/43session.tests +++ b/tests/43session.tests @@ -29,7 +29,44 @@ PLANNED "DeleteClip_test" DeleteClip_test < ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-1 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-2 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-1 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-2 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.>.+ use-cnt=4 +out: Asset\(VIDEO:lumi.test-1 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-1 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: MRef-NIL +out: sizeof\( .+MORef.+session.Clip.+ \) = (32)|(24) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Asset\(VIDEO:lumi.test-2 v1\) +out: Placement<.+Clip.> ............... use-cnt=4 +out: Placement<.+Clip.> ............... use-cnt=5 +out: \(VIDEO:lumi.test-1 v1\) END diff --git a/tests/components/proc/mobject/mobject-ref-test.cpp b/tests/components/proc/mobject/mobject-ref-test.cpp index b202636eb..2bd8239a7 100644 --- a/tests/components/proc/mobject/mobject-ref-test.cpp +++ b/tests/components/proc/mobject/mobject-ref-test.cpp @@ -46,8 +46,30 @@ using std::endl; namespace mobject { namespace test { + namespace { // shortcut for checking use-counts + + bool + checkUseCount (size_t cnt, uint additional=0) + { + static uint base_count=0; + if (!additional) // called for init + base_count = cnt; + + return cnt == base_count + additional; + } + + template + bool + checkUseCount (REF const& ref, uint additional) + { + return checkUseCount(ref.use_count(), additional); + } + } + + using lumiera::Time; using session::Clip; + using session::PMedia; using session::SessionServiceMockIndex; using session::PPIdx; @@ -105,6 +127,10 @@ namespace test { PMObj& pClip1 = index->find(clip1ID); PMObj& pClip2 = index->find(clip2ID); + ASSERT (3 == pClip1.use_count()); // clip-Asset, original placement, new placement in index + ASSERT (3 == pClip2.use_count()); + checkUseCount(pClip1.use_count()); // set ref point for later checks + // extract various kinds of IDs and refs PMObj & rP1 (pClip1); PMObj const& rP2 (pClip2); @@ -147,25 +173,29 @@ namespace test { template void - checkBuildMObjectRef (REF refObj, void* placementAdr) + checkBuildMObjectRef (REF& refObj, void* placementAdr) { MORef rMO; ASSERT (!rMO); // still empty (not bound) - cout << rMO << endl; + ASSERT (0==rMO.use_count()); + cout << string(rMO) << endl; /////////////////////TICKET #527 cout << showSizeof(rMO) << endl; // activate by binding to provided ref rMO.activate(refObj); ASSERT (rMO); // now bound - cout << rMO << endl; + cout << string(rMO) << endl; /////////////////////TICKET #527 // access MObject (Clip API) // cout << rMO->operator string() << endl; /////////////////////TICKET #428 - cout << string(rMO->getMedia()->ident) << endl; /////////////////////TICKET #520 + PMedia media = rMO->getMedia(); + cout << str(media) << endl; /////////////////////TICKET #520 + Time mediaLength = media->getLength(); + ASSERT (Time(0) < mediaLength); ASSERT (rMO->isValid()); // access the Placement-API - ASSERT (3 == rMO.use_count()); // now rMO shares ownership with the Placement + ASSERT (checkUseCount(rMO, 1)); // now rMO shares ownership with the Placement --> use-count += 1 ASSERT (Time(0) < rMO.getStartTime()); // (internally, this resolves to an ExplicitPlacement) /////////TICKET #332 ASSERT ( rMO.isCompatible()); ASSERT ( rMO.isCompatible()); @@ -175,14 +205,15 @@ namespace test { // re-link to the Placement (note we get the Clip API!) Placement & refP = rMO.getPlacement(); ASSERT (refP.isValid()); - ASSERT (3 == refP.use_count()); + ASSERT (refP.use_count() == rMO.use_count()); + ASSERT (checkUseCount(refP, 1)); // use count not changed 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 (4 == refP.use_count()); // but now we've indeed created an additional owner (exPla) - ASSERT (4 == rMO.use_count()); + ASSERT (checkUseCount(refP, 2)); // but now we've indeed created an additional owner (exPla) + ASSERT (checkUseCount(rMO, 2)); } @@ -243,21 +274,21 @@ namespace test { ASSERT (!(rM == pRef1) && !(pRef1 == rM)); ASSERT ( (rM != pRef1) && (pRef1 != rM)); - ASSERT (!(rM != pRef2) && !(pRef2 != rM)); - ASSERT ( (rM == pRef2) && (pRef2 == rM)); + ASSERT ( (rM != pRef2) && (pRef2 != rM)); + ASSERT (!(rM == pRef2) && !(pRef2 == rM)); ASSERT (!(rM == p1.getID()) ); ASSERT ( (rM != p1.getID()) ); - ASSERT (!(rM != p2.getID()) ); - ASSERT ( (rM == p2.getID()) ); + ASSERT ( (rM != p2.getID()) ); + ASSERT (!(rM == p2.getID()) ); } void checkLifecycle (PMObj const& p1, PMObj const& p2) { - ASSERT (2 == p1.use_count()); - ASSERT (2 == p2.use_count()); + ASSERT (checkUseCount(p1, 0)); + ASSERT (checkUseCount(p2, 0)); MORef rMO; ASSERT (!rMO); @@ -266,27 +297,27 @@ namespace test { rMO.activate(p1); ASSERT (rMO); ASSERT (rMO->getMedia()->getFilename() == "test-1"); - ASSERT (3 == rMO.use_count()); - ASSERT (3 == p1.use_count()); - ASSERT (2 == p2.use_count()); + ASSERT (checkUseCount(rMO, 1)); + ASSERT (checkUseCount(p1, 1)); // sharing ownership + ASSERT (checkUseCount(p2, 0)); rMO.activate(p2); ASSERT (rMO); ASSERT (rMO->getMedia()->getFilename() == "test-2"); - ASSERT (3 == rMO.use_count()); - ASSERT (2 == p1.use_count()); - ASSERT (3 == p2.use_count()); + ASSERT (checkUseCount(rMO, 1)); + ASSERT (checkUseCount(p1, 0)); // detached, use count dropped to previous value + ASSERT (checkUseCount(p2, 1)); // sharing ownership rMO.activate(p2); - ASSERT (3 == rMO.use_count()); + ASSERT (checkUseCount(rMO, 1)); // no change rMO.close(); ASSERT (!rMO); - ASSERT (2 == p1.use_count()); - ASSERT (2 == p2.use_count()); + ASSERT (checkUseCount(p1, 0)); + ASSERT (checkUseCount(p2, 0)); - VERIFY_ERROR (INVALID_PLACEMENTREF, rMO.getPlacement() ); - VERIFY_ERROR (BOTTOM_MOBJECTREF, rMO->getMedia() ); + VERIFY_ERROR (BOTTOM_MOBJECTREF, rMO.getPlacement() ); + VERIFY_ERROR (BOTTOM_MOBJECTREF, rMO->getMedia() ); } void @@ -296,19 +327,19 @@ namespace test { MORef rClip; MORef rSub1; - ASSERT (0 == rMObj.use_count()); - ASSERT (0 == rClip.use_count()); - ASSERT (0 == rSub1.use_count()); + ASSERT ( ! rMObj.use_count()); + ASSERT ( ! rClip.use_count()); + ASSERT ( ! rSub1.use_count()); rMObj.activate(luid); - ASSERT (3 == rMObj.use_count()); - ASSERT (0 == rClip.use_count()); - ASSERT (0 == rSub1.use_count()); + ASSERT (checkUseCount(rMObj, 1)); + ASSERT ( ! rClip.use_count()); + ASSERT ( ! rSub1.use_count()); rClip.activate(rMObj); // attach on existing MObjectRef - ASSERT (4 == rMObj.use_count()); - ASSERT (4 == rClip.use_count()); - ASSERT (0 == rSub1.use_count()); + ASSERT (checkUseCount(rMObj, 2)); + ASSERT (checkUseCount(rClip, 2)); + ASSERT ( ! rSub1.use_count()); // impossible, because Clip isn't a subclass of TestSubMO1: VERIFY_ERROR (INVALID_PLACEMENTREF, rSub1.activate(luid) ); @@ -322,15 +353,15 @@ namespace test { // rMObj->getMedia(); rClip.close(); - ASSERT (3 == rMObj.use_count()); - ASSERT (0 == rClip.use_count()); + ASSERT (checkUseCount(rMObj, 1)); + ASSERT ( ! rClip.use_count()); - // can assign, because the actual type checked: + // can assign, because the actual type is checked: rClip = rMObj; - ASSERT (4 == rMObj.use_count()); - ASSERT (4 == rClip.use_count()); + ASSERT (checkUseCount(rMObj, 2)); + ASSERT (checkUseCount(rClip, 2)); - cout << rClip << endl; + cout << string(rClip) << endl; //////////TICKET #527 cout << string(rClip->getMedia()->ident) << endl; //////////TICKET #520 } }; diff --git a/tests/lib/typed-counter-test.cpp b/tests/lib/typed-counter-test.cpp index 68eefc988..3828f396f 100644 --- a/tests/lib/typed-counter-test.cpp +++ b/tests/lib/typed-counter-test.cpp @@ -71,8 +71,8 @@ namespace test{ namespace { // test data and helpers... - const uint MAX_FAMILIES = 5; ///< maximum separate "families", each sharing a TypedCounter - const uint MAX_MEMBERS = 20; ///< maximum members per family (member == test thread) + const uint MAX_FAMILIES = 4; ///< maximum separate "families", each sharing a TypedCounter + const uint MAX_MEMBERS = 10; ///< maximum members per family (member == test thread) const uint MAX_ITERATIONS = 50; ///< maximum iterations within a single test thread const uint MAX_DELAY_ms = 3; ///< maximum delay between check iterations