draft a mixin for adding element-tracking functionality
This commit is contained in:
parent
bdb21c4aa8
commit
55df5205a4
4 changed files with 199 additions and 48 deletions
115
src/lib/element-tracker.hpp
Normal file
115
src/lib/element-tracker.hpp
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
ELEMENT-TRACKER.hpp - registry for tracking instances automatically
|
||||||
|
|
||||||
|
Copyright (C) Lumiera.org
|
||||||
|
2010, Hermann Vosseler <Ichthyostega@web.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** @file element-tracker.hpp
|
||||||
|
** Tracking instances automatically on creation and disposal.
|
||||||
|
** Part of the Session interface is exposed as self-contained
|
||||||
|
** interface modules -- both for notational convenience at the
|
||||||
|
** usage site, and for keeping session implementation code manageable.
|
||||||
|
** Clients access these modules as nested parts of the public Session interface
|
||||||
|
** through references exposing just the respective interfaces, while the actual
|
||||||
|
** implementation is located in-place (within the SesssionImpl object), packaged
|
||||||
|
** into a non-public baseclass.
|
||||||
|
** - the DefsManager acts as frontend to the system of default configurations
|
||||||
|
** and config rules, allowing to retrieve the \em default version of various
|
||||||
|
** kinds of objects
|
||||||
|
** - the top-level Timeline (structural assets) act as facade and entry point
|
||||||
|
** to the high-level-model (session contents). There is an table of timelines,
|
||||||
|
** managed automatically and kept in sync with the session::Binding elements
|
||||||
|
** located directly below model root.
|
||||||
|
** - likewise there is an table of all Sequence (structural assets), which
|
||||||
|
** correspond to the roots of track trees, attached below model root.
|
||||||
|
**
|
||||||
|
** \par maintaining the link between session, timelines and sequences
|
||||||
|
** Timeline and Sequence are implemented as asset::Struct, causing them to be
|
||||||
|
** maintained by the AssetManager, which in turn is attached to the session::Root
|
||||||
|
** (WIP 3/2010: yet to be implemented). Creation and destruction of timelines and
|
||||||
|
** sequences is closely connected to some structural changes within the model
|
||||||
|
** - Timeline is related to session::Binding, where the timelines are leading
|
||||||
|
** and the binding elements are dependent on both a timeline and a sequence
|
||||||
|
** - Sequence is related to a Placement<session::Track> -- but only if attached
|
||||||
|
** immediately below model root; here the tracks are leading and the sequences
|
||||||
|
** are completely dependent.
|
||||||
|
** In any case, ctor and dtor of Timeline and Sequence have to care for proper
|
||||||
|
** registration into the SessionInterfaceModules for timelines and sequences
|
||||||
|
** respectively. This is accomplished by using kind-of a backdoor, a SessionServices
|
||||||
|
** (proc internal API) definition, allowing direct communication on implementation
|
||||||
|
** level, without the need to expose this access point on the public session API.
|
||||||
|
** The impl::ElementTracker implemented in this sourcefile here relieves these
|
||||||
|
** calls to maintain a list of asset smart-ptrs
|
||||||
|
**
|
||||||
|
** @see SessionImpl
|
||||||
|
** @see session-services.hpp
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LIB_ELEMENT_TRACKER_H
|
||||||
|
#define LIB_ELEMENT_TRACKER_H
|
||||||
|
|
||||||
|
#include "lib/p.hpp"
|
||||||
|
#include "lib/ref-array-impl.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace lib {
|
||||||
|
|
||||||
|
using lumiera::P;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom implementation of the RefArray interface,
|
||||||
|
* used by the Session to keep track of all timelines
|
||||||
|
* and sequences. The registration/deregistration functions
|
||||||
|
* are accessible as SessionServices
|
||||||
|
*/
|
||||||
|
template<typename ELM>
|
||||||
|
class ElementTracker
|
||||||
|
: public lib::RefArrayVectorWrapper<P<ELM> >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
append (P<ELM> const& asset)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("attach entry to session");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remove (ELM const& asset)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("detach entry from session");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isRegistered (ELM const& asset)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED ("detect if the given element is indeed registered within this");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lib
|
||||||
|
#endif
|
||||||
|
|
@ -89,7 +89,7 @@ namespace asset {
|
||||||
bool known (IDA id, const Category& cat) ;
|
bool known (IDA id, const Category& cat) ;
|
||||||
|
|
||||||
/**remove the given asset from the internal DB.
|
/**remove the given asset from the internal DB.
|
||||||
* <i>together with all its dependants</i> */
|
* <i>together with all its dependents</i> */
|
||||||
void remove (IDA id) ;
|
void remove (IDA id) ;
|
||||||
|
|
||||||
/** extract a sorted list of all registered Assets */
|
/** extract a sorted list of all registered Assets */
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,7 @@
|
||||||
#ifndef MOBJECT_SESSION_INTERFACE_MODULES_H
|
#ifndef MOBJECT_SESSION_INTERFACE_MODULES_H
|
||||||
#define MOBJECT_SESSION_INTERFACE_MODULES_H
|
#define MOBJECT_SESSION_INTERFACE_MODULES_H
|
||||||
|
|
||||||
#include "lib/p.hpp"
|
#include "lib/element-tracker.hpp"
|
||||||
#include "lib/ref-array-impl.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -76,39 +75,10 @@
|
||||||
namespace mobject {
|
namespace mobject {
|
||||||
namespace session {
|
namespace session {
|
||||||
|
|
||||||
namespace impl { // impl: list of elements to track
|
|
||||||
|
|
||||||
using lumiera::P;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom implementation of the RefArray interface,
|
|
||||||
* used by the Session to keep track of all timelines
|
|
||||||
* and sequences. The registration/deregistration functions
|
|
||||||
* are accessible as SessionServices
|
|
||||||
*/
|
|
||||||
template<typename ELM>
|
|
||||||
class ElementTracker
|
|
||||||
: public lib::RefArrayVectorWrapper<P<ELM> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void
|
|
||||||
add (P<ELM> const& asset)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("attach entry to session");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
remove (P<ELM> const& asset)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED ("detach entry from session");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} //(End) impl list of elements to track
|
|
||||||
|
|
||||||
|
|
||||||
typedef impl::ElementTracker<asset::Timeline> TimelineTracker;
|
typedef lib::ElementTracker<asset::Timeline> TimelineTracker;
|
||||||
typedef impl::ElementTracker<asset::Sequence> SequenceTracker;
|
typedef lib::ElementTracker<asset::Sequence> SequenceTracker;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
//#include "lib/util.hpp"
|
//#include "lib/util.hpp"
|
||||||
|
|
||||||
//#include <iostream>
|
//#include <iostream>
|
||||||
|
#include <tr1/functional>
|
||||||
|
|
||||||
//using util::isSameObject;
|
//using util::isSameObject;
|
||||||
//using util::contains;
|
//using util::contains;
|
||||||
|
|
@ -53,36 +54,96 @@ namespace test {
|
||||||
|
|
||||||
int checksum = 0;
|
int checksum = 0;
|
||||||
|
|
||||||
class AutoRegisteringDummy;
|
|
||||||
|
|
||||||
typedef lumiera::P<AutoRegisteringDummy> PDummy;
|
using std::tr1::function;
|
||||||
|
using std::tr1::bind;
|
||||||
|
using std::tr1::ref;
|
||||||
|
|
||||||
class AutoRegisteringDummy
|
|
||||||
|
template<typename TAR>
|
||||||
|
class AutoRegistered
|
||||||
|
{
|
||||||
|
typedef lib::ElementTracker<TAR> Registry;
|
||||||
|
typedef function<Registry&(void)> RegistryLink;
|
||||||
|
|
||||||
|
static RegistryLink getRegistry;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename FUN>
|
||||||
|
static void
|
||||||
|
establishRegistryLink (FUN link)
|
||||||
|
{
|
||||||
|
AutoRegistered::getRegistry = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setRegistryInstance (Registry& registry_to_use)
|
||||||
|
{
|
||||||
|
establishRegistryLink (bind (ref(registry_to_use)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef lumiera::P<TAR> PTarget;
|
||||||
|
|
||||||
|
static PTarget
|
||||||
|
create()
|
||||||
|
{
|
||||||
|
REQUIRE (getRegistry);
|
||||||
|
|
||||||
|
PTarget newElement (new TAR());
|
||||||
|
getRegistry().append (newElement);
|
||||||
|
|
||||||
|
ENSURE (newElement);
|
||||||
|
ENSURE (getRegistry().isRegistered(*newElement));
|
||||||
|
return newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
detach()
|
||||||
|
{
|
||||||
|
getRegistry().remove(*this);
|
||||||
|
|
||||||
|
ENSURE (!getRegistry().isRegistered(*this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** storage for the functor to link an AutoRegistered entity
|
||||||
|
* to the corresponding registration service */
|
||||||
|
template<typename TAR>
|
||||||
|
AutoRegistered<TAR>::RegistryLink AutoRegistered<TAR>::getRegistry;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Dummy: to be created through the inherited static #create(),
|
||||||
|
* managed by smart-ptr. Any Dummy instance gets automatically registered
|
||||||
|
* for tracking, and will be deregistered by invoking #unlink().
|
||||||
|
* The link to the actual registration service has to be established at
|
||||||
|
* runtime once, by calling #establishRegistryLink or #setRegistryInstance
|
||||||
|
*/
|
||||||
|
struct Dummy
|
||||||
|
: AutoRegistered<Dummy>
|
||||||
{
|
{
|
||||||
const uint id_;
|
const uint id_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoRegisteringDummy()
|
Dummy()
|
||||||
: id_(++checksum)
|
: id_(++checksum)
|
||||||
{
|
{
|
||||||
TODO ("cause the registration");
|
CHECK (getRegistry().isRegistered (*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
unlink()
|
unlink()
|
||||||
{
|
{
|
||||||
TODO ("cause the deregistration");
|
getRegistry().remove(*this);
|
||||||
checksum -= id_;
|
checksum -= id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PDummy create();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PDummy
|
|
||||||
AutoRegisteringDummy::create()
|
|
||||||
{
|
|
||||||
return PDummy (new AutoRegisteringDummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// using proc_interface::AssetManager;
|
// using proc_interface::AssetManager;
|
||||||
|
|
@ -123,11 +184,16 @@ namespace test {
|
||||||
{
|
{
|
||||||
checksum = 0;
|
checksum = 0;
|
||||||
{
|
{
|
||||||
impl::ElementTracker<AutoRegisteringDummy> trackedDummies;
|
typedef Dummy AutoRegisteringDummy;
|
||||||
|
typedef lumiera::P<AutoRegisteringDummy> PDummy;
|
||||||
|
typedef lib::ElementTracker<Dummy> DummyRegistry;
|
||||||
|
|
||||||
|
DummyRegistry trackedDummies;
|
||||||
|
|
||||||
CHECK (0 == checksum);
|
CHECK (0 == checksum);
|
||||||
CHECK (0 == trackedDummies.size());
|
CHECK (0 == trackedDummies.size());
|
||||||
|
|
||||||
|
AutoRegisteringDummy::setRegistryInstance (trackedDummies);
|
||||||
PDummy dummy1 = AutoRegisteringDummy::create();
|
PDummy dummy1 = AutoRegisteringDummy::create();
|
||||||
PDummy dummy2 = AutoRegisteringDummy::create();
|
PDummy dummy2 = AutoRegisteringDummy::create();
|
||||||
|
|
||||||
|
|
@ -152,7 +218,7 @@ namespace test {
|
||||||
CHECK (2 == dummy3.use_count());
|
CHECK (2 == dummy3.use_count());
|
||||||
|
|
||||||
// deliberately discard our reference,
|
// deliberately discard our reference,
|
||||||
// so the only remaining ref is in the tracker
|
// so the only remaining ref is within the registry
|
||||||
dummy1.reset();
|
dummy1.reset();
|
||||||
dummy2.reset();
|
dummy2.reset();
|
||||||
CHECK (1 == trackedDummies[0].use_count());
|
CHECK (1 == trackedDummies[0].use_count());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue