implement registry for element-tracking. passes unit test
This commit is contained in:
parent
9ec865c3ab
commit
dd3d22f950
4 changed files with 112 additions and 34 deletions
|
|
@ -50,6 +50,7 @@
|
||||||
#define LIB_ELEMENT_TRACKER_H
|
#define LIB_ELEMENT_TRACKER_H
|
||||||
|
|
||||||
#include "lib/p.hpp"
|
#include "lib/p.hpp"
|
||||||
|
#include "lib/util-foreach.hpp"
|
||||||
#include "lib/ref-array-impl.hpp"
|
#include "lib/ref-array-impl.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,32 +61,87 @@ namespace lib {
|
||||||
using lumiera::P;
|
using lumiera::P;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Registry for tracking object instances.
|
||||||
* Custom implementation of the RefArray interface,
|
* Custom implementation of the RefArray interface,
|
||||||
* used by the Session to keep track of all timelines
|
* based on a vector. Especially used by the Session
|
||||||
* and sequences. The registration/deregistration functions
|
* to keep track of all timelines and sequences.
|
||||||
* are accessible as SessionServices
|
* Typically, ELM will inherit from AutoRegistered<ELM>,
|
||||||
|
* which in turn will invoke the registration/deregistration.
|
||||||
|
* Because of the smart-ptr-from-this problem, removal takes
|
||||||
|
* a direct reference, as opposed to a smart-ptr.
|
||||||
|
* @note ELM is required to provide an equality test.
|
||||||
|
* Depending on the semantics of this equality,
|
||||||
|
* registration might behave surprisingly, as
|
||||||
|
* previously registered \em equivalent instances
|
||||||
|
* will be deregistered prior to appending the
|
||||||
|
* new instance.
|
||||||
*/
|
*/
|
||||||
template<typename ELM>
|
template<typename ELM>
|
||||||
class ElementTracker
|
class ElementTracker
|
||||||
: public lib::RefArrayVector<P<ELM> >
|
: public lib::RefArrayVector<P<ELM> >
|
||||||
{
|
{
|
||||||
|
typedef std::vector<P<ELM> > _Vec;
|
||||||
|
typedef typename _Vec::iterator Iter;
|
||||||
|
typedef typename _Vec::const_iterator CIter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~ElementTracker()
|
||||||
|
{
|
||||||
|
try { clear(); }
|
||||||
|
catch(...) {/*ignored*/}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear ()
|
||||||
|
{
|
||||||
|
_Vec toKill;
|
||||||
|
toKill.reserve(_Vec::size());
|
||||||
|
toKill.swap(*this);
|
||||||
|
ASSERT (0 == _Vec::size());
|
||||||
|
util::for_each (toKill, unlink_it);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
append (P<ELM> const& asset)
|
append (P<ELM> const& asset)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("attach entry to session");
|
REQUIRE (asset, "Attempt to track a NIL element");
|
||||||
|
remove (*asset);
|
||||||
|
push_back (asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
remove (ELM const& asset)
|
remove (ELM const& asset)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("detach entry from session");
|
for (Iter i = _Vec::begin();
|
||||||
|
i != _Vec::end() ; ++i )
|
||||||
|
if (asset == **i) // _Vec contains smart-ptrs
|
||||||
|
{ // ELM is required to define '=='
|
||||||
|
erase (i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isRegistered (ELM const& asset)
|
isRegistered (ELM const& asset) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED ("detect if the given element is indeed registered within this");
|
for (CIter i = _Vec::begin();
|
||||||
|
i != _Vec::end() ; ++i )
|
||||||
|
if (asset == **i)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void
|
||||||
|
unlink_it (P<ELM>& elm)
|
||||||
|
{
|
||||||
|
REQUIRE (elm);
|
||||||
|
try { elm->detach(); }
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
WARN (common,"ignoring problems while clearing ElementTracker");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ namespace asset {
|
||||||
: public Struct
|
: public Struct
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
void detach() { TODO("Session-Sequence registration"); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Sequence (const Asset::Ident& idi);
|
Sequence (const Asset::Ident& idi);
|
||||||
friend class StructFactoryImpl;
|
friend class StructFactoryImpl;
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,9 @@ namespace asset {
|
||||||
: public Struct
|
: public Struct
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
void detach() { TODO("Timeline-Session registration"); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Timeline (const Asset::Ident& idi);
|
Timeline (const Asset::Ident& idi);
|
||||||
friend class StructFactoryImpl;
|
friend class StructFactoryImpl;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ namespace test {
|
||||||
|
|
||||||
namespace { // yet another accounting dummy
|
namespace { // yet another accounting dummy
|
||||||
|
|
||||||
|
uint instance = 0;
|
||||||
int checksum = 0;
|
int checksum = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -82,19 +83,17 @@ namespace test {
|
||||||
typedef lib::ElementTracker<TAR> Registry;
|
typedef lib::ElementTracker<TAR> Registry;
|
||||||
typedef function<Registry&(void)> RegistryLink;
|
typedef function<Registry&(void)> RegistryLink;
|
||||||
|
|
||||||
|
// virtual ~AutoRegistered() {} ////////////////////////////////////TODO template code bloat?
|
||||||
template<typename FUN>
|
//
|
||||||
static void
|
// virtual void ////////////////////////////////////TODO clarify de-registration
|
||||||
establishRegistryLink (FUN link)
|
void
|
||||||
|
detach()
|
||||||
{
|
{
|
||||||
AutoRegistered::getRegistry = link;
|
#if false ///////////////////////////////////////////////////////////////////////////TODO clarify de-registration
|
||||||
}
|
getRegistry().remove(*this);
|
||||||
|
|
||||||
static void
|
ENSURE (!getRegistry().isRegistered(*this));
|
||||||
setRegistryInstance (Registry& registry_to_use)
|
#endif ///////////////////////////////////////////////////////////////////////////TODO clarify de-registration
|
||||||
{
|
|
||||||
RegistryLink accessInstance = ReturnRef<Registry>(registry_to_use);
|
|
||||||
establishRegistryLink (accessInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -114,12 +113,18 @@ namespace test {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
template<typename FUN>
|
||||||
detach()
|
static void
|
||||||
|
establishRegistryLink (FUN link)
|
||||||
{
|
{
|
||||||
getRegistry().remove(*this);
|
AutoRegistered::getRegistry = link;
|
||||||
|
}
|
||||||
|
|
||||||
ENSURE (!getRegistry().isRegistered(*this));
|
static void
|
||||||
|
setRegistryInstance (Registry& registry_to_use)
|
||||||
|
{
|
||||||
|
RegistryLink accessInstance = ReturnRef<Registry>(registry_to_use);
|
||||||
|
establishRegistryLink (accessInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -144,22 +149,29 @@ namespace test {
|
||||||
{
|
{
|
||||||
const uint id_;
|
const uint id_;
|
||||||
|
|
||||||
public:
|
|
||||||
Dummy()
|
Dummy()
|
||||||
: id_(++checksum)
|
: id_(++instance)
|
||||||
{
|
{
|
||||||
CHECK (getRegistry().isRegistered (*this));
|
checksum += id_;
|
||||||
}
|
}
|
||||||
|
// to be created by factory...
|
||||||
|
friend class AutoRegistered<Dummy>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// virtual void /////////////////////////////TODO
|
||||||
void
|
void
|
||||||
unlink()
|
detach()
|
||||||
{
|
{
|
||||||
getRegistry().remove(*this);
|
getRegistry().remove(*this);
|
||||||
|
|
||||||
|
ENSURE (!getRegistry().isRegistered(*this));
|
||||||
|
///////////////////////////////////////////////////////////////TODO: should call the baseclass!
|
||||||
|
// AutoRegistered<Dummy>::detach();
|
||||||
checksum -= id_;
|
checksum -= id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
operator== (Dummy const& d1, Dummy const& d2)
|
operator== (Dummy const& d1, Dummy const& d2)
|
||||||
{
|
{
|
||||||
|
|
@ -198,13 +210,14 @@ namespace test {
|
||||||
run (Arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
verify_trackingMechanism();
|
verify_trackingMechanism();
|
||||||
verify_integration();
|
// verify_integration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
verify_trackingMechanism()
|
verify_trackingMechanism()
|
||||||
{
|
{
|
||||||
|
instance = 0;
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
{
|
{
|
||||||
typedef Dummy AutoRegisteringDummy;
|
typedef Dummy AutoRegisteringDummy;
|
||||||
|
|
@ -230,7 +243,7 @@ namespace test {
|
||||||
|
|
||||||
CHECK (1+2+3 == checksum);
|
CHECK (1+2+3 == checksum);
|
||||||
|
|
||||||
dummy2->unlink();
|
dummy2->detach();
|
||||||
CHECK (1 + 3 == checksum);
|
CHECK (1 + 3 == checksum);
|
||||||
CHECK (2 == trackedDummies.size());
|
CHECK (2 == trackedDummies.size());
|
||||||
CHECK (dummy1 == trackedDummies[0]);
|
CHECK (dummy1 == trackedDummies[0]);
|
||||||
|
|
@ -243,7 +256,10 @@ namespace test {
|
||||||
// deliberately discard our reference,
|
// deliberately discard our reference,
|
||||||
// so the only remaining ref is within the registry
|
// so the only remaining ref is within the registry
|
||||||
dummy1.reset();
|
dummy1.reset();
|
||||||
dummy2.reset();
|
dummy3.reset();
|
||||||
|
CHECK (!dummy1);
|
||||||
|
CHECK ( dummy2);
|
||||||
|
CHECK (!dummy3);
|
||||||
CHECK (1 == trackedDummies[0].use_count());
|
CHECK (1 == trackedDummies[0].use_count());
|
||||||
CHECK (1 == trackedDummies[1].use_count());
|
CHECK (1 == trackedDummies[1].use_count());
|
||||||
CHECK (1 + 3 == checksum);
|
CHECK (1 + 3 == checksum);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue