some naming cleanup and namespace indentation fixes

This commit is contained in:
Fischlurch 2010-12-18 00:58:19 +01:00
parent 3f1b7651e9
commit 7fc462209e
39 changed files with 1732 additions and 1741 deletions

View file

@ -35,7 +35,7 @@ liblumiera_la_LIBADD = \
liblumiera_la_SOURCES = \
$(liblumiera_la_srcdir)/advice/advice.cpp \
$(liblumiera_la_srcdir)/advice/binding.cpp \
$(liblumiera_la_srcdir)/allocationcluster.cpp \
$(liblumiera_la_srcdir)/allocation-cluster.cpp \
$(liblumiera_la_srcdir)/cmdline.cpp \
$(liblumiera_la_srcdir)/condition.c \
$(liblumiera_la_srcdir)/error.c \
@ -69,8 +69,8 @@ noinst_HEADERS += \
$(liblumiera_la_srcdir)/advice.hpp \
$(liblumiera_la_srcdir)/advice/binding.hpp \
$(liblumiera_la_srcdir)/advice/index.hpp \
$(liblumiera_la_srcdir)/allocationcluster.hpp \
$(liblumiera_la_srcdir)/allocationcluster.hpp \
$(liblumiera_la_srcdir)/allocation-cluster.hpp \
$(liblumiera_la_srcdir)/allocation-cluster.hpp \
$(liblumiera_la_srcdir)/condition.h \
$(liblumiera_la_srcdir)/error.h \
$(liblumiera_la_srcdir)/error.hpp \
@ -103,9 +103,9 @@ noinst_HEADERS += \
$(liblumiera_la_srcdir)/scoped-holder.hpp \
$(liblumiera_la_srcdir)/singleton-subclass.hpp \
$(liblumiera_la_srcdir)/singleton.hpp \
$(liblumiera_la_srcdir)/singletonfactory.hpp \
$(liblumiera_la_srcdir)/singletonpolicies.hpp \
$(liblumiera_la_srcdir)/singletonpreconfigure.hpp \
$(liblumiera_la_srcdir)/singleton-factory.hpp \
$(liblumiera_la_srcdir)/singleton-policies.hpp \
$(liblumiera_la_srcdir)/singleton-preconfigure.hpp \
$(liblumiera_la_srcdir)/sync-classlock.hpp \
$(liblumiera_la_srcdir)/sync.hpp \
$(liblumiera_la_srcdir)/sync.hpp \

View file

@ -21,7 +21,7 @@
* *****************************************************/
#include "lib/allocationcluster.hpp"
#include "lib/allocation-cluster.hpp"
#include "lib/error.hpp"
#include "lib/util.hpp"
#include "lib/sync.hpp"

View file

@ -1,5 +1,5 @@
/*
ALLOCATIONCLUSTER.hpp - allocating and owning a pile of objects
ALLOCATION-CLUSTER.hpp - allocating and owning a pile of objects
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -20,7 +20,7 @@
*/
/** @file allocationcluster.hpp
/** @file allocation-cluster.hpp
** Memory management for the low-level model (render nodes network).
** The model is organised into temporal segments, which are considered
** to be structurally constant and uniform. The objects within each
@ -35,17 +35,17 @@
** templates, and thus need to be in the header. This way they can
** exploit the type information available in call context. This
** information is passed to generic implementation functions
** defined in allocationcluster.cpp . In a similar vein, the
** defined in allocation-cluster.cpp . In a similar vein, the
** AllocationCluster::MemoryManger is just forward declared.
**
** @see allocationclustertest.cpp
** @see allocation-cluster-test.cpp
** @see builder::ToolFactory
** @see frameid.hpp
*/
#ifndef LIB_ALLOCATIONCLUSTER_H
#define LIB_ALLOCATIONCLUSTER_H
#ifndef LIB_ALLOCATION_CLUSTER_H
#define LIB_ALLOCATION_CLUSTER_H
#include <vector>
#include <boost/scoped_ptr.hpp>

View file

@ -1,5 +1,5 @@
/*
SINGLETONFACTORY.hpp - template for implementing the singleton pattern
SINGLETON-FACTORY.hpp - template for implementing the singleton pattern
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -31,11 +31,11 @@ This code is heavily inspired by
#ifndef LIB_SINGLETONFACTORY_H
#define LIB_SINGLETONFACTORY_H
#ifndef LIB_SINGLETON_FACTORY_H
#define LIB_SINGLETON_FACTORY_H
#include "lib/singletonpolicies.hpp" // several Policies usable together with SingletonFactory
#include "lib/singleton-policies.hpp" // several Policies usable together with SingletonFactory
#include "lib/nobug-init.hpp"
#include "include/logging.h"

View file

@ -0,0 +1,138 @@
/*
SINGLETON-POLICIES.hpp - how to manage creation, lifecycle and multithreading
Copyright (C) Lumiera.org
2008, 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.
====================================================================
This code is heavily inspired by
The Loki Library (loki-lib/trunk/include/loki/Singleton.h)
Copyright (c) 2001 by Andrei Alexandrescu
This Loki code accompanies the book:
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming
and Design Patterns Applied".
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
*/
#ifndef LIB_SINGLETON_POLICIES_H
#define LIB_SINGLETON_POLICIES_H
#include "lib/nobug-init.hpp"
#include "lib/error.hpp"
#include <vector>
namespace lib {
namespace singleton {
/* === several Policies usable in conjunction with lib::Singleton === */
/**
* Policy placing the Singleton instance into a statically allocated buffer
*/
template<class S>
struct StaticCreate
{
static S* create ()
{
#if NOBUG_MODE_ALPHA
static uint callCount = 0;
ASSERT ( 0 == callCount++ );
#endif
static char buff[sizeof(S)];
return new(buff) S();
}
static void destroy (S* pSi)
{
pSi-> ~S();
}
};
/**
* Policy for creating the Singleton instance heap allocated
*/
template<class S>
struct HeapCreate
{
static S* create () { return new S; }
static void destroy (S* pS) { delete pS; }
};
typedef void (*DelFunc)(void);
using std::vector;
/**
* Policy relying on the compiler/runtime system for Singleton Lifecycle
*/
template<class S>
struct AutoDestroy
{
/** implements the Singleton removal by calling
* the provided deleter function(s) at application shutdown,
* relying on the runtime system calling destructors of static
* objects. Because this Policy class can be shared between
* several Singletons, we need to memorise all registered
* deleter functions for calling them at shutdown.
*/
static void
scheduleDelete (DelFunc kill_the_singleton)
{
class DeleteTrigger
{
vector<DelFunc> dels_;
public:
void schedule (DelFunc del)
{
dels_.push_back(del);
}
~DeleteTrigger()
{
vector<DelFunc>::iterator i = dels_.begin();
for ( ; i != dels_.end(); ++i )
(*i)(); // invoke deleter function
}
};
REQUIRE (kill_the_singleton);
static DeleteTrigger finally;
finally.schedule (kill_the_singleton);
}
static void
onDeadReference ()
{
throw lumiera::error::Logic ("Trying to access the a Singleton instance that has "
"already been released or finished its lifecycle.");
}
};
}} // namespace lib::singleton
#endif

View file

@ -1,5 +1,5 @@
/*
SINGLETONPRECONFIGURE - declare the configuration of some Singleton types in advance
SINGLETON-PRECONFIGURE - declare the configuration of some Singleton types in advance
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -20,7 +20,7 @@
*/
/** @file singletonpreconfigure.hpp
/** @file singleton-preconfigure.hpp
** Pre-configuration of some Singleton types, done by template specialisation.
** Typically the client code just includes singleton.h and uses the Singleton
** type. But in some cases, we want to configure specific (dependency injection)
@ -37,12 +37,12 @@
** @note we declare the specialisations into the target namespace
**
** @see SingletonFactory
** @see singletontestmocktest.hpp
** @see SingletonTestMock_test
*/
#ifndef LIB_SINGLETONPRECONFIGURE_H
#define LIB_SINGLETONPRECONFIGURE_H
#ifndef LIB_SINGLETON_PRECONFIGURE_H
#define LIB_SINGLETON_PRECONFIGURE_H
#include "lib/test/mockinjector.hpp"

View file

@ -24,19 +24,19 @@
** Factory for creating Singleton instances.
** This configuration header just pulls in some other implementation headers in
** the right order. The basic class template for creating singletons resides in
** singletonfactory.hpp, besides we need policy classes defining how to create
** singleton-factory.hpp, besides we need policy classes defining how to create
** the singleton objects and how to manage singleton lifecycle. Finally,
** we want to preconfigure singleton factories for some important facilities;
** e.g. sometimes we want to include a hook for injecting Test Mock instances.
**
** You'll find the default Policies in singletonfactory.hpp and the default
** definition of type lumiera::singleton in singletonpreconfigure.hpp
** You'll find the default Policies in singleton-factory.hpp and the default
** definition of type lumiera::singleton in singleton-preconfigure.hpp
**
** @see SingletonFactory
** @see singleton::StaticCreate
** @see singleton::AutoDestroy
** @see singletontest.hpp
** @see singletontestmocktest.hpp
** @see SingletonTestMock_test
*/
@ -44,9 +44,9 @@
#define LIB_SINGLETON_H
#include "lib/singletonpolicies.hpp"
#include "lib/singletonfactory.hpp"
#include "lib/singletonpreconfigure.hpp"
#include "lib/singleton-policies.hpp"
#include "lib/singleton-factory.hpp"
#include "lib/singleton-preconfigure.hpp"
#endif

View file

@ -1,138 +0,0 @@
/*
SINGLETONPOLICIES.hpp - how to manage creation, lifecycle and multithreading
Copyright (C) Lumiera.org
2008, 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.
====================================================================
This code is heavily inspired by
The Loki Library (loki-lib/trunk/include/loki/Singleton.h)
Copyright (c) 2001 by Andrei Alexandrescu
This Loki code accompanies the book:
Alexandrescu, Andrei. "Modern C++ Design: Generic Programming
and Design Patterns Applied".
Copyright (c) 2001. Addison-Wesley. ISBN 0201704315
*/
#ifndef LIB_SINGLETONPOLICIES_H
#define LIB_SINGLETONPOLICIES_H
#include "lib/nobug-init.hpp"
#include "lib/error.hpp"
#include <vector>
namespace lib {
namespace singleton {
/* === several Policies usable in conjunction with lib::Singleton === */
/**
* Policy placing the Singleton instance into a statically allocated buffer
*/
template<class S>
struct StaticCreate
{
static S* create ()
{
#ifdef DEBUG
static uint callCount = 0;
ASSERT ( 0 == callCount++ );
#endif
static char buff[sizeof(S)];
return new(buff) S();
}
static void destroy (S* pSi)
{
pSi-> ~S();
}
};
/**
* Policy for creating the Singleton instance heap allocated
*/
template<class S>
struct HeapCreate
{
static S* create () { return new S; }
static void destroy (S* pS) { delete pS; }
};
typedef void (*DelFunc)(void);
using std::vector;
/**
* Policy relying on the compiler/runtime system for Singleton Lifecycle
*/
template<class S>
struct AutoDestroy
{
/** implements the Singleton removal by calling
* the provided deleter function(s) at application shutdown,
* relying on the runtime system calling destructors of static
* objects. Because this Policy class can be shared between
* several Singletons, we need to memorise all registered
* deleter functions for calling them at shutdown.
*/
static void
scheduleDelete (DelFunc kill_the_singleton)
{
class DeleteTrigger
{
vector<DelFunc> dels_;
public:
void schedule (DelFunc del)
{
dels_.push_back(del);
}
~DeleteTrigger()
{
vector<DelFunc>::iterator i = dels_.begin();
for ( ; i != dels_.end(); ++i )
(*i)(); // invoke deleter func
}
};
REQUIRE (kill_the_singleton);
static DeleteTrigger finally;
finally.schedule (kill_the_singleton);
}
static void
onDeadReference ()
{
throw lumiera::error::Logic ("Trying to access the a Singleton instance that has "
"already been released or finished its lifecycle.");
}
};
}} // namespace lib::singleton
#endif

View file

@ -29,7 +29,7 @@
**
** @note simply using the ClassLock may cause a Monitor object (with a mutex) to be
** created at static initialisation and destroyed on application shutdown.
** @see singletonfactory.hpp usage example
** @see singleton-factory.hpp usage example
*/

View file

@ -26,7 +26,7 @@
#define LUMIERA_TEST_MOCKINJECTOR_H
#include "lib/singletonfactory.hpp"
#include "lib/singleton-factory.hpp"
#include <boost/scoped_ptr.hpp>

View file

@ -155,7 +155,7 @@ liblumiprocmobjectsession_la_SOURCES = \
$(liblumiprocmobjectsession_la_srcdir)/clip.cpp \
$(liblumiprocmobjectsession_la_srcdir)/compoundclip.cpp \
$(liblumiprocmobjectsession_la_srcdir)/constraint.cpp \
$(liblumiprocmobjectsession_la_srcdir)/defsmanager.cpp \
$(liblumiprocmobjectsession_la_srcdir)/defs-manager.cpp \
$(liblumiprocmobjectsession_la_srcdir)/effect.cpp \
$(liblumiprocmobjectsession_la_srcdir)/fixedlocation.cpp \
$(liblumiprocmobjectsession_la_srcdir)/fixture.cpp \
@ -237,8 +237,8 @@ noinst_HEADERS += \
$(liblumiproc_la_srcdir)/mobject/session/clip.hpp \
$(liblumiproc_la_srcdir)/mobject/session/compoundclip.hpp \
$(liblumiproc_la_srcdir)/mobject/session/constraint.hpp \
$(liblumiproc_la_srcdir)/mobject/session/defsmanager.hpp \
$(liblumiproc_la_srcdir)/mobject/session/defsregistry.hpp \
$(liblumiproc_la_srcdir)/mobject/session/defs-manager.hpp \
$(liblumiproc_la_srcdir)/mobject/session/defs-registry.hpp \
$(liblumiproc_la_srcdir)/mobject/session/effect.hpp \
$(liblumiproc_la_srcdir)/mobject/session/fixedlocation.hpp \
$(liblumiproc_la_srcdir)/mobject/session/fixture.hpp \

View file

@ -23,7 +23,7 @@
#include "proc/engine/nodefactory.hpp"
#include "proc/mobject/session/effect.hpp"
#include "lib/allocationcluster.hpp"
#include "lib/allocation-cluster.hpp"
#include "proc/engine/nodewiring.hpp"

View file

@ -26,7 +26,7 @@
#include "proc/engine/procnode.hpp"
#include "lib/allocationcluster.hpp"
#include "lib/allocation-cluster.hpp"
#include "proc/engine/nodewiring-def.hpp"
//#include <boost/noncopyable.hpp>

View file

@ -51,7 +51,7 @@
#include "proc/mobject/placement.hpp"
#include "proc/mobject/mobject-ref.hpp"
#include "proc/mobject/session/defsmanager.hpp" ////////////////////////////TICKET #643 forward declare this?
#include "proc/mobject/session/defs-manager.hpp" ////////////////////////////TICKET #643 forward declare this?
#include "lib/ref-array.hpp"
#include "lib/singleton.hpp"
#include "lib/symbol.hpp"

View file

@ -21,8 +21,8 @@
* *****************************************************/
#include "proc/mobject/session/defsmanager.hpp"
#include "proc/mobject/session/defsregistry.hpp"
#include "proc/mobject/session/defs-manager.hpp"
#include "proc/mobject/session/defs-registry.hpp"
#include "common/configrules.hpp"
#include "lib/error.hpp"

View file

@ -0,0 +1,128 @@
/*
DEFS-MANAGER.hpp - access to preconfigured default objects and definitions
Copyright (C) Lumiera.org
2008, 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.
*/
#ifndef MOBJECT_SESSION_DEFS_MANAGER_H
#define MOBJECT_SESSION_DEFS_MANAGER_H
#include "lib/p.hpp"
#include "lib/query.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/noncopyable.hpp>
namespace mobject {
namespace session {
using lumiera::P;
using boost::scoped_ptr;
namespace impl { class DefsRegistry; }
/**
* Organise a collection of preconfigured default objects.
* For various kinds of objects we can tweak the default parametrisation
* as part of the general session configuration. A ref to an instance of
* this class is accessible through the current session and can be used
* to fill in parts of the configuration of new objects, if the user
* code didn't give more specific parameters. Necessary sub-objects
* will be created on demand, and any default configuration, once
* found, will be remembered and stored with the current session.
*
* @note while the logic of defaults handling can be considered
* roughly final, as of 12/09 most of the actual object
* handling is placeholder code.
*/
class DefsManager : private boost::noncopyable
{
scoped_ptr<impl::DefsRegistry> defsRegistry;
public:
DefsManager () throw();
~DefsManager ();
/** common access point: retrieve the default object fulfilling
* some given conditions. May silently trigger object creation.
* @throw error::Config in case no solution is possible, which
* is considered \e misconfiguration.
*/
template<class TAR>
P<TAR> operator() (lumiera::Query<TAR> const&);
/** search through the registered defaults, never create anything.
* @return object fulfilling the query, \c empty ptr if not found.
*/
template<class TAR>
P<TAR> search (lumiera::Query<TAR> const&);
/** retrieve an object fulfilling the query and register it as default.
* The resolution is delegated to the ConfigQuery system (which may cause
* creation of new object instances)
* @return object fulfilling the query, \c empty ptr if no solution.
*/
template<class TAR>
P<TAR> create (lumiera::Query<TAR> const&);
/** register the given object as default, after ensuring it fulfils the
* query. The latter may cause some properties of the object to be set,
* trigger creation of additional objects, and may fail altogether.
* @return true if query was successful and object is registered as default
* @note only a weak ref to the object is stored
*/
template<class TAR>
bool define (P<TAR> const&, lumiera::Query<TAR> const& =lumiera::Query<TAR>());
/** remove the defaults registration of the given object, if there was such
* @return false if nothing has been changed because the object wasn't registered
*/
template<class TAR>
bool forget (P<TAR> const&);
// Q: can we have something along the line of...?
//
// template
// < class TAR, ///< the target to query for
// template <class> class SMP ///< smart pointer class to wrap the result
// >
// SMP<TAR> operator() (const lumiera::Query<TAR>&);
// 12/09: according to my current knowledge of template metaprogramming, the answer is "no",
// but we could use a traits template to set up a fixed association of smart pointers
// and kinds of target object. This would allow to define a templated operator() returning
// the result wrapped into the right holder. But currently I don't see how to build a sensible
// implementation infrastructure backing such an interface.
//////////TICKET #452
};
}} // namespace mobject::session
#endif

View file

@ -1,5 +1,5 @@
/*
DEFSREGISTRY.hpp - implementation of the default object store
DEFS-REGISTRY.hpp - implementation of the default object store
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
@ -21,23 +21,23 @@
*/
/** @file defsregistry.hpp
/** @file defs-registry.hpp
** A piece of implementation code factored out into a separate header (include).
** Only used in defsmanager.cpp and for the unit tests. We can't place it into
** a separate compilation unit, because defsmanager.cpp defines some explicit
** Only used in defs-manager.cpp and for the unit tests. We can't place it into
** a separate compilation unit, because defs-manager.cpp defines some explicit
** template instantiation, which cause the different Slots of the DefsrRegistry#table_
** to be filled with data and defaults for the specific Types.
**
** @see mobject::session::DefsManager
** @see defsregistryimpltest.cpp
** @see DefsRegistryImpl_test
**
*/
#ifndef MOBJECT_SESSION_DEFSREGISTRY_H
#define MOBJECT_SESSION_DEFSREGISTRY_H
#ifndef MOBJECT_SESSION_DEFS_REGISTRY_H
#define MOBJECT_SESSION_DEFS_REGISTRY_H
#include "lib/sync-classlock.hpp"
@ -340,8 +340,5 @@ namespace mobject {
using impl::DefsRegistry;
} // namespace mobject::session
} // namespace mobject
}} // namespace mobject::session
#endif

View file

@ -1,130 +0,0 @@
/*
DEFSMANAGER.hpp - access to preconfigured default objects and definitions
Copyright (C) Lumiera.org
2008, 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.
*/
#ifndef MOBJECT_SESSION_DEFSMANAGER_H
#define MOBJECT_SESSION_DEFSMANAGER_H
#include "lib/p.hpp"
#include "lib/query.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/noncopyable.hpp>
namespace mobject {
namespace session {
using lumiera::P;
using boost::scoped_ptr;
namespace impl { class DefsRegistry; }
/**
* Organise a collection of preconfigured default objects.
* For various kinds of objects we can tweak the default parametrisation
* as part of the general session configuration. A ref to an instance of
* this class is accessible through the current session and can be used
* to fill in parts of the configuration of new objects, if the user
* code didn't give more specific parameters. Necessary sub-objects
* will be created on demand, and any default configuration, once
* found, will be remembered and stored with the current session.
*
* @note while the logic of defaults handling can be considered
* roughly final, as of 12/09 most of the actual object
* handling is placeholder code.
*/
class DefsManager : private boost::noncopyable
{
scoped_ptr<impl::DefsRegistry> defsRegistry;
public:
DefsManager () throw();
~DefsManager ();
/** common access point: retrieve the default object fulfilling
* some given conditions. May silently trigger object creation.
* @throw error::Config in case no solution is possible, which
* is considered \e misconfiguration.
*/
template<class TAR>
P<TAR> operator() (lumiera::Query<TAR> const&);
/** search through the registered defaults, never create anything.
* @return object fulfilling the query, \c empty ptr if not found.
*/
template<class TAR>
P<TAR> search (lumiera::Query<TAR> const&);
/** retrieve an object fulfilling the query and register it as default.
* The resolution is delegated to the ConfigQuery system (which may cause
* creation of new object instances)
* @return object fulfilling the query, \c empty ptr if no solution.
*/
template<class TAR>
P<TAR> create (lumiera::Query<TAR> const&);
/** register the given object as default, after ensuring it fulfils the
* query. The latter may cause some properties of the object to be set,
* trigger creation of additional objects, and may fail altogether.
* @return true if query was successful and object is registered as default
* @note only a weak ref to the object is stored
*/
template<class TAR>
bool define (P<TAR> const&, lumiera::Query<TAR> const& =lumiera::Query<TAR>());
/** remove the defaults registration of the given object, if there was such
* @return false if nothing has been changed because the object wasn't registered
*/
template<class TAR>
bool forget (P<TAR> const&);
// Q: can we have something along the line of...?
//
// template
// < class TAR, ///< the target to query for
// template <class> class SMP ///< smart pointer class to wrap the result
// >
// SMP<TAR> operator() (const lumiera::Query<TAR>&);
// 12/09: according to my current knowledge of template metaprogramming, the answer is "no",
// but we could use a traits template to set up a fixed association of smart pointers
// and kinds of target object. This would allow to define a templated operator() returning
// the result wrapped into the right holder. But currently I don't see how to build a sensible
// implementation infrastructure backing such an interface.
//////////TICKET #452
};
} // namespace mobject::session
} // namespace mobject
#endif

View file

@ -22,7 +22,7 @@
#include "proc/mobject/session/root.hpp"
#include "proc/mobject/session/defsmanager.hpp"
#include "proc/mobject/session/defs-manager.hpp"
namespace mobject {

View file

@ -40,7 +40,7 @@
#include "proc/mobject/session.hpp"
#include "proc/mobject/session/sess-manager-impl.hpp"
#include "proc/mobject/session/defsmanager.hpp"
#include "proc/mobject/session/defs-manager.hpp"
#include "proc/mobject/session/lifecycle-advisor.hpp"
#include "proc/asset/timeline.hpp"
#include "lib/error.hpp"

View file

@ -73,7 +73,7 @@
#include "lib/element-tracker.hpp"
#include "proc/asset/timeline.hpp"
#include "proc/asset/sequence.hpp"
#include "proc/mobject/session/defsmanager.hpp"
#include "proc/mobject/session/defs-manager.hpp"
#include "proc/mobject/session/element-query.hpp"

View file

@ -32,7 +32,7 @@
#include "proc/mobject/session.hpp"
#include "proc/mobject/session/defsmanager.hpp"
#include "proc/mobject/session/defs-manager.hpp"
#include "proc/mobject/session/session-impl.hpp"
#include "proc/mobject/session/sess-manager-impl.hpp"

View file

@ -85,9 +85,9 @@ test_components_SOURCES = \
$(testcomponents_srcdir)/proc/mobject/placement-object-identity-test.cpp \
$(testcomponents_srcdir)/proc/mobject/placement-ref-test.cpp \
$(testcomponents_srcdir)/proc/mobject/session/addcliptest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsmanagerimpltest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsmanagertest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defsregistryimpltest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defs-manager-impl-test.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defs-manager-test.cpp \
$(testcomponents_srcdir)/proc/mobject/session/defs-registry-impl-test.cpp \
$(testcomponents_srcdir)/proc/mobject/session/deletecliptest.cpp \
$(testcomponents_srcdir)/proc/mobject/session/placement-index-query-test.cpp \
$(testcomponents_srcdir)/proc/mobject/session/placement-index-test.cpp \

View file

@ -28,7 +28,7 @@
#include "proc/engine/stateproxy.hpp"
#include "proc/engine/buffhandle.hpp"
#include "proc/mobject/session/effect.hpp"
#include "lib/allocationcluster.hpp"
#include "lib/allocation-cluster.hpp"
//#include <boost/format.hpp>
//#include <iostream>

View file

@ -30,10 +30,8 @@
#include "lib/util.hpp"
#include "proc/mobject/session/mobjectfactory.hpp" ////TODO: avoidable?
//#include <boost/format.hpp>
#include <iostream>
//using boost::format;
using lumiera::Time;
using util::contains;
using std::string;
@ -94,8 +92,4 @@ namespace mobject {
} // namespace test
} // namespace session
} // namespace mobject
}}} // namespace mobject::session::test

View file

@ -0,0 +1,176 @@
/*
DefsManagerImpl(Test) - checking implementation details of the defaults manager
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "pre_a.hpp"
#include "lib/test/run.hpp"
#include "lib/util.hpp"
#include "proc/asset.hpp"
#include "proc/asset/pipe.hpp"
#include "proc/asset/struct.hpp"
#include "common/configrules.hpp"
#include "proc/assetmanager.hpp"
#include "proc/mobject/session.hpp"
#include "lib/streamtype.hpp"
#include <boost/format.hpp>
using boost::format;
using util::isnil;
using std::string;
namespace mobject {
namespace session {
namespace test {
using lib::Symbol;
using asset::Asset;
using asset::AssetManager;
using asset::Pipe;
using asset::PPipe;
using asset::Struct;
using lumiera::Query;
using lumiera::query::normaliseID;
using lumiera::ConfigRules;
using lumiera::query::QueryHandler;
using lumiera::StreamType;
/** shortcut: query for given Pipe-ID */
bool
find (const string& pID)
{
return Session::current->defaults.search (Query<Pipe> ("pipe("+pID+")"));
}
format pattern ("dummy_%s_%i");
/** create a random new ID */
string
newID (Symbol prefix)
{
return str (pattern % prefix % std::rand());
}
/************************************************************************
* @test verify some general assumptions regarding implementation details
* of the the defaults manager.
* @see DefsManager_test for the "big picture"
*/
class DefsManagerImpl_test : public Test
{
virtual void
run(Arg)
{
define_and_search();
string pipeID = create();
forget(pipeID);
}
void
define_and_search ()
{
string sID = newID ("stream");
StreamType::ID stID (sID);
// create Pipes explicitly
// (without utilising default queries)
PPipe pipe1 = Struct::retrieve.newPipe (newID("pipe"), newID("stream"));
PPipe pipe2 = Struct::retrieve.newPipe (newID("pipe"), sID );
CHECK (pipe1 != pipe2);
CHECK (stID == pipe2->getStreamID());
CHECK (!find (pipe1->getPipeID()), "accidental clash of random test-IDs");
CHECK (!find (pipe2->getPipeID()), "accidental clash of random test-IDs");
// now declare that these objects should be considered "default"
lumiera::query::setFakeBypass(""); /////////////////////////////////////////////////TODO mock resolution
CHECK (Session::current->defaults.define (pipe1, Query<Pipe> (""))); // unrestricted default
lumiera::query::setFakeBypass("stream("+sID+")"); ///////////////////////////////////TODO mock resolution
CHECK (Session::current->defaults.define (pipe2, Query<Pipe> ("stream("+sID+")")));
CHECK ( find (pipe1->getPipeID()), "failure declaring object as default");
CHECK ( find (pipe2->getPipeID()), "failure declaring object as default");
CHECK (stID != pipe1->getStreamID(), "accidental clash");
CHECK (!Session::current->defaults.define (pipe1, Query<Pipe> ("stream("+sID+")")));
// can't be registered with this query, due to failure caused by wrong stream-ID
}
const string&
create()
{
string sID = newID ("stream");
Query<Pipe> query_for_streamID ("stream("+sID+")");
// issue a ConfigQuery directly, without involving the DefaultsManager
QueryHandler<Pipe>& typeHandler = ConfigRules::instance();
PPipe pipe1;
typeHandler.resolve (pipe1, query_for_streamID);
CHECK (pipe1);
CHECK (!find (pipe1->getPipeID()));
PPipe pipe2 = Session::current->defaults.create (query_for_streamID);
CHECK (pipe2);
CHECK (pipe2 == pipe1);
CHECK ( find (pipe1->getPipeID())); // now declared as "default Pipe" for this stream-ID
return pipe1->getPipeID();
}
void
forget (string pID)
{
PPipe pipe = Pipe::query ("pipe("+pID+")");
REQUIRE (find (pipe->getPipeID()), "need an object registered as default");
long cnt = pipe.use_count();
// now de-register the pipe as "default Pipe"
CHECK (Session::current->defaults.forget (pipe));
CHECK (!find (pipe->getPipeID()));
CHECK (cnt == pipe.use_count()); // indicates DefaultsManager holding only a weak ref.
}
};
/** Register this test class... */
LAUNCHER (DefsManagerImpl_test, "function session");
}}} // namespace mobject::session::test

View file

@ -0,0 +1,204 @@
/*
DefsManager(Test) - checking basic behaviour of the defaults manager
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "pre_a.hpp"
#include "lib/test/run.hpp"
#include "lib/symbol.hpp"
#include "lib/query.hpp"
#include "lib/util.hpp"
#include "proc/asset.hpp"
#include "proc/asset/pipe.hpp"
#include "proc/asset/struct.hpp"
#include "proc/assetmanager.hpp"
#include "proc/mobject/session.hpp"
#include "lib/streamtype.hpp"
#include <boost/format.hpp>
using boost::format;
using util::isnil;
using std::string;
namespace mobject {
namespace session {
namespace test {
using util::cStr;
using lib::Symbol;
using asset::ID;
using asset::Asset;
using asset::AssetManager;
using asset::Pipe;
using asset::PPipe;
using asset::Struct;
using lumiera::Query;
using lumiera::query::normaliseID;
using lumiera::StreamType;
/** shortcut: run just a query
* without creating new instances
*/
bool
find (Query<Pipe>& q)
{
return Session::current->defaults.search (q);
}
/***********************************************************************
* @test basic behaviour of the defaults manager ("the big picture")
* - retrieving a "default" object repeatedly
* - retrieving a more constrained "default" object
* - failure registers a new "default"
* - instance management
*
* Using pipe assets as an example. The defaults manager shouldn't
* interfere with memory management (it holds weak refs).
*/
class DefsManager_test : public Test
{
virtual void
run (Arg arg)
{
string pipeID = isnil(arg)? "Black Hole" : arg[1];
string streamID = 2>arg.size()? "teststream" : arg[2];
normaliseID (pipeID);
normaliseID (streamID);
retrieveSimpleDefault (pipeID);
retrieveConstrainedDefault (pipeID, streamID);
failureCreatesNewDefault();
verifyRemoval();
}
void
retrieveSimpleDefault (string)
{
PPipe pipe1 = Pipe::query (""); // "the default pipe"
PPipe pipe2;
// several variants to query for "the default pipe"
pipe2 = Pipe::query ("");
CHECK (pipe2 == pipe1);
pipe2 = Pipe::query ("default(X)");
CHECK (pipe2 == pipe1);
pipe2 = Session::current->defaults(Query<Pipe> ());
CHECK (pipe2 == pipe1);
pipe2 = asset::Struct::retrieve (Query<Pipe> ());
CHECK (pipe2 == pipe1);
pipe2 = asset::Struct::retrieve (Query<Pipe> ("default(P)"));
CHECK (pipe2 == pipe1);
}
void
retrieveConstrainedDefault (string pID, string sID)
{
PPipe pipe1 = Pipe::query (""); // "the default pipe"
CHECK ( pipe1->getStreamID() != StreamType::ID(sID),
"stream-ID \"%s\" not suitable for test, because "
"the default-pipe \"%s\" happens to have the same "
"stream-ID. We need it to be different",
sID.c_str(), pID.c_str()
);
string query_for_sID ("stream("+sID+")");
PPipe pipe2 = Pipe::query (query_for_sID);
CHECK (pipe2->getStreamID() == StreamType::ID(sID));
CHECK (pipe2 != pipe1);
CHECK (pipe2 == Pipe::query (query_for_sID)); // reproducible
}
void
failureCreatesNewDefault()
{
PPipe pipe1 = Session::current->defaults(Query<Pipe> ()); // "the default pipe"
string new_pID (str (format ("dummy_%s_%i")
% pipe1->getPipeID()
% std::rand()
)); // make random new pipeID
Query<Pipe> query_for_new ("pipe("+new_pID+")");
CHECK (!find (query_for_new)); // check it doesn't exist
PPipe pipe2 = Session::current->defaults (query_for_new); // triggers creation
CHECK ( find (query_for_new)); // check it exists now
CHECK (pipe1 != pipe2);
CHECK (pipe2 == Session::current->defaults (query_for_new));
}
/** verify the defaults manager holds only weak refs,
* so if an object goes out of scope, any defaults entries
* are purged silently
*/
void
verifyRemoval()
{
Symbol pID ("some_pipe");
Query<Pipe> query_for_pID ("pipe("+pID+")");
size_t hash;
{
// create new pipe and declare it to be a default
PPipe pipe1 = Struct::retrieve.newInstance<Pipe> (pID);
Session::current->defaults.define(pipe1);
CHECK (2 == pipe1.use_count()); // the pipe1 smart-ptr and the AssetManager
hash = pipe1->getID();
}
// pipe1 out of scope....
// AssetManager now should hold the only ref
ID<Asset> assetID (hash);
AssetManager& aMang (AssetManager::instance());
CHECK ( aMang.known (assetID));
aMang.remove (assetID);
CHECK (!aMang.known (assetID));
CHECK (!find(query_for_pID)); // bare default-query should fail...
PPipe pipe2 = Session::current->defaults (query_for_pID); // triggers re-creation
CHECK ( find(query_for_pID)); // should succeed again
}
};
/** Register this test class... */
LAUNCHER (DefsManager_test, "function session");
}}} // namespace mobject::session::test

View file

@ -0,0 +1,292 @@
/*
DefsRegistryImpl(Test) - verifying correct behaviour of the defaults registry
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/util.hpp"
#include "proc/mobject/session/defs-registry.hpp"
#include "lib/factory.hpp"
#include "lib/query.hpp"
#include "lib/p.hpp"
#include "../lib/query/querydiagnostics.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/format.hpp>
#include <map>
using lumiera::P;
using lumiera::Query;
using lumiera::query::test::garbage_query;
using util::isnil;
using boost::scoped_ptr;
using boost::format;
using std::string;
using std::rand;
using std::map;
namespace mobject {
namespace session {
namespace test {
format typePatt ("Dummy<%2i>");
format instancePatt ("obj_%s_%i");
format predicatePatt ("%s_%2i( %s )");
/** create a random new ID */
string
newID (string prefix)
{
return str (instancePatt % prefix % rand());
}
/** template for generating some different test types */
template<int I>
struct Dummy
{
static string name;
string instanceID;
operator string () const { return instanceID; }
bool operator== (const Dummy& odu) const { return this == &odu; }
Dummy () : instanceID (newID (name)) {}
};
template<int I>
string Dummy<I>::name = str (typePatt % I);
/************************************************************************
* @test build an registry table (just for this test) configured for
* some artificial test Types. Register some entries and verify
* the intended behaviour of the storage structure.
* @see DefsManagerImpl_test for checking the implementation details
* in the actual context used in Lumiera.
*/
class DefsRegistryImpl_test : public Test
{
scoped_ptr<DefsRegistry> reg_;
typedef lumiera::P<Dummy<13> > O;
typedef lumiera::P<Dummy<23> > P;
typedef Query<Dummy<13> > Q13;
typedef Query<Dummy<23> > Q23;
typedef DefsRegistry::Iter<Dummy<13> > Iter13;
typedef DefsRegistry::Iter<Dummy<23> > Iter23;
// fabricating Objects wrapped into smart-ptrs
lib::factory::RefcountFac<Dummy<13> > oFac;
lib::factory::RefcountFac<Dummy<23> > pFac;
O o1, o2, o3;
Q13 q1, q2, q3, q4, q5;
map<Q23, P> ps;
public:
DefsRegistryImpl_test ()
: o1 (oFac()), o2 (oFac()), o3 (oFac()),
q1 (garbage_query (1)),
q2 (garbage_query (2)),
q3 (garbage_query (3)),
q4 (garbage_query (4)),
q5 (garbage_query (5))
{ }
virtual void
run (Arg)
{
this->reg_.reset (new DefsRegistry);
fill_table ();
check_query ();
check_remove ();
}
void
fill_table ()
{
// at start the registry is indeed empty
// thus a query doesn't yield any results....
CHECK ( ! *(reg_->candidates(Q13 ("something"))) );
reg_->put (o1, q5);
reg_->put (o2, q4);
reg_->put (o3, q3);
reg_->put (o3, q2);
reg_->put (o2, q1);
reg_->put (o1, Q13()); // the empty query
ps.clear();
for (int i=0; i<100; ++i)
{
P px (pFac());
Q23 qx (garbage_query());
ps[qx] = px;
reg_->put (px, qx);
px->instanceID = qx;
}
}
void
check_query ()
{
Iter13 i (reg_->candidates(Q13 ("irrelevant query")));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i == o1);
CHECK (!i.hasNext());
CHECK (! *++i ); // null after end
i = reg_->candidates(q3);
CHECK ( *i++ == o3); // found by direct match
CHECK ( *i++ == o1); // followed by the ordered enumeration
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
i = reg_->candidates(Q13());
CHECK ( *i++ == o1); // found by direct match to the empty query
CHECK ( *i++ == o1);
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
uint d=0;
uint d_prev=0;
Iter23 j = reg_->candidates(Q23 ("some crap"));
for ( ; *j ; ++j )
{
CHECK ( *j );
Q23 qx ((*j)->instanceID);
CHECK ( ps[qx] == (*j));
d = lumiera::query::countPred (qx);
CHECK ( d_prev <= d );
d_prev = d;
}
CHECK (!j.hasNext());
// calling with an arbitrary (registered) query
// yields the corresponding object at start of the enumeration
j = reg_->candidates(ps.begin()->first);
CHECK ( *j == ps.begin()->second);
}
void
check_remove ()
{
reg_->forget (o2);
Iter13 i (reg_->candidates(q4));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
// but the o2 entries are missing
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
// missing
CHECK ( *i == o1);
CHECK (!i.hasNext());
o3.reset(); // killing the only reference....
// expires the weak ref in the registry
i = reg_->candidates(Q13 ("something"));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
// but now also the o3 entries are missing...
CHECK ( *i == o1);
CHECK (!i.hasNext());
CHECK ( reg_->put (o1, q5)); // trying to register the same object at the same place
// doesn't change anything (but counts as "success")
i = reg_->candidates(q5);
CHECK ( *i++ == o1); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK (!reg_->put (o2, q5)); // trying to (re)register o2 with a existing query
// counts as failure (nothing changes)
i = reg_->candidates(q5);
CHECK ( *i++ == o1); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK ( reg_->put (o2, q2)); // trying to (re)register o2 with another query succeeds
i = reg_->candidates(q2);
CHECK ( *i++ == o2); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o2); // inserted here in the dataset
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK ( reg_->forget (o1));
CHECK (!reg_->forget (o1)); // failure, because it's already removed
CHECK ( reg_->forget (o2));
o3 = oFac(); // another object is another object (it's irrelevant...)
i = reg_->candidates(q2);
CHECK (! (*i)); // empty
}
};
/** Register this test class... */
LAUNCHER (DefsRegistryImpl_test, "function session");
}}} // namespace mobject::session::test

View file

@ -1,172 +0,0 @@
/*
DefsManagerImpl(Test) - checking implementation details of the defaults manager
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "pre_a.hpp"
#include "lib/test/run.hpp"
#include "lib/util.hpp"
#include "proc/asset.hpp"
#include "proc/asset/pipe.hpp"
#include "common/configrules.hpp"
#include "proc/assetmanager.hpp"
#include "proc/mobject/session.hpp"
#include "lib/streamtype.hpp"
#include <boost/format.hpp>
using boost::format;
using util::isnil;
using std::string;
namespace asset {
namespace test {
using mobject::Session;
using lib::Symbol;
using lumiera::Query;
using lumiera::query::normaliseID;
using lumiera::ConfigRules;
using lumiera::query::QueryHandler;
using lumiera::StreamType;
/** shortcut: query for given Pipe-ID */
bool
find (const string& pID)
{
return Session::current->defaults.search (Query<Pipe> ("pipe("+pID+")"));
}
format pattern ("dummy_%s_%i");
/** create a random new ID */
string
newID (Symbol prefix)
{
return str (pattern % prefix % std::rand());
}
/************************************************************************
* @test verify some general assumptions regarding implementation details
* of the the defaults manager.
* @see DefsManager_test for the "big picture"
*/
class DefsManagerImpl_test : public Test
{
virtual void
run(Arg)
{
define_and_search();
string pipeID = create();
forget(pipeID);
}
void
define_and_search ()
{
string sID = newID ("stream");
StreamType::ID stID (sID);
// create Pipes explicitly
// (without utilising default queries)
PPipe pipe1 = Struct::retrieve.newPipe (newID("pipe"), newID("stream"));
PPipe pipe2 = Struct::retrieve.newPipe (newID("pipe"), sID );
CHECK (pipe1 != pipe2);
CHECK (stID == pipe2->getStreamID());
CHECK (!find (pipe1->getPipeID()), "accidental clash of random test-IDs");
CHECK (!find (pipe2->getPipeID()), "accidental clash of random test-IDs");
// now declare that these objects should be considered "default"
lumiera::query::setFakeBypass(""); /////////////////////////////////////////////////TODO mock resolution
CHECK (Session::current->defaults.define (pipe1, Query<Pipe> (""))); // unrestricted default
lumiera::query::setFakeBypass("stream("+sID+")"); ///////////////////////////////////TODO mock resolution
CHECK (Session::current->defaults.define (pipe2, Query<Pipe> ("stream("+sID+")")));
CHECK ( find (pipe1->getPipeID()), "failure declaring object as default");
CHECK ( find (pipe2->getPipeID()), "failure declaring object as default");
CHECK (stID != pipe1->getStreamID(), "accidental clash");
CHECK (!Session::current->defaults.define (pipe1, Query<Pipe> ("stream("+sID+")")));
// can't be registered with this query, due to failure caused by wrong stream-ID
}
const string&
create()
{
string sID = newID ("stream");
Query<Pipe> query_for_streamID ("stream("+sID+")");
// issue a ConfigQuery directly, without involving the DefaultsManager
QueryHandler<Pipe>& typeHandler = ConfigRules::instance();
PPipe pipe1;
typeHandler.resolve (pipe1, query_for_streamID);
CHECK (pipe1);
CHECK (!find (pipe1->getPipeID()));
PPipe pipe2 = Session::current->defaults.create (query_for_streamID);
CHECK (pipe2);
CHECK (pipe2 == pipe1);
CHECK ( find (pipe1->getPipeID())); // now declared as "default Pipe" for this stream-ID
return pipe1->getPipeID();
}
void
forget (string pID)
{
PPipe pipe = Pipe::query ("pipe("+pID+")");
REQUIRE (find (pipe->getPipeID()), "need an object registered as default");
long cnt = pipe.use_count();
// now de-register the pipe as "default Pipe"
CHECK (Session::current->defaults.forget (pipe));
CHECK (!find (pipe->getPipeID()));
CHECK (cnt == pipe.use_count()); // indicates DefaultsManager holding only a weak ref.
}
};
/** Register this test class... */
LAUNCHER (DefsManagerImpl_test, "function session");
} // namespace test
} // namespace asset

View file

@ -1,197 +0,0 @@
/*
DefsManager(Test) - checking basic behaviour of the defaults manager
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "pre_a.hpp"
#include "lib/test/run.hpp"
#include "lib/symbol.hpp"
#include "lib/query.hpp"
#include "lib/util.hpp"
#include "proc/asset.hpp"
#include "proc/asset/pipe.hpp"
#include "proc/assetmanager.hpp"
#include "proc/mobject/session.hpp"
#include "lib/streamtype.hpp"
#include <boost/format.hpp>
using boost::format;
using util::isnil;
using std::string;
namespace asset {
namespace test {
using util::cStr;
using lib::Symbol;
using mobject::Session;
using lumiera::Query;
using lumiera::query::normaliseID;
using lumiera::StreamType;
/** shortcut: run just a query
* without creating new instances
*/
bool
find (Query<Pipe>& q)
{
return Session::current->defaults.search (q);
}
/***********************************************************************
* @test basic behaviour of the defaults manager ("the big picture")
* - retrieving a "default" object repeatedly
* - retrieving a more constrained "default" object
* - failure registers a new "default"
* - instance management
*
* Using pipe assets as an example. The defaults manager shouldn't
* interfere with memory management (it holds weak refs).
*/
class DefsManager_test : public Test
{
virtual void
run (Arg arg)
{
string pipeID = isnil(arg)? "Black Hole" : arg[1];
string streamID = 2>arg.size()? "teststream" : arg[2] ;
normaliseID (pipeID);
normaliseID (streamID);
retrieveSimpleDefault (pipeID);
retrieveConstrainedDefault (pipeID, streamID);
failureCreatesNewDefault();
verifyRemoval();
}
void
retrieveSimpleDefault (string)
{
PPipe pipe1 = Pipe::query (""); // "the default pipe"
PPipe pipe2;
// several variants to query for "the default pipe"
pipe2 = Pipe::query ("");
CHECK (pipe2 == pipe1);
pipe2 = Pipe::query ("default(X)");
CHECK (pipe2 == pipe1);
pipe2 = Session::current->defaults(Query<Pipe> ());
CHECK (pipe2 == pipe1);
pipe2 = asset::Struct::retrieve (Query<Pipe> ());
CHECK (pipe2 == pipe1);
pipe2 = asset::Struct::retrieve (Query<Pipe> ("default(P)"));
CHECK (pipe2 == pipe1);
}
void
retrieveConstrainedDefault (string pID, string sID)
{
PPipe pipe1 = Pipe::query (""); // "the default pipe"
CHECK ( pipe1->getStreamID() != StreamType::ID(sID),
"stream-ID \"%s\" not suitable for test, because "
"the default-pipe \"%s\" happens to have the same "
"stream-ID. We need it to be different",
sID.c_str(), pID.c_str()
);
string query_for_sID ("stream("+sID+")");
PPipe pipe2 = Pipe::query (query_for_sID);
CHECK (pipe2->getStreamID() == StreamType::ID(sID));
CHECK (pipe2 != pipe1);
CHECK (pipe2 == Pipe::query (query_for_sID)); // reproducible
}
void
failureCreatesNewDefault()
{
PPipe pipe1 = Session::current->defaults(Query<Pipe> ()); // "the default pipe"
string new_pID (str (format ("dummy_%s_%i")
% pipe1->getPipeID()
% std::rand()
)); // make random new pipeID
Query<Pipe> query_for_new ("pipe("+new_pID+")");
CHECK (!find (query_for_new)); // check it doesn't exist
PPipe pipe2 = Session::current->defaults (query_for_new); // triggers creation
CHECK ( find (query_for_new)); // check it exists now
CHECK (pipe1 != pipe2);
CHECK (pipe2 == Session::current->defaults (query_for_new));
}
/** verify the defaults manager holds only weak refs,
* so if an object goes out of scope, any defaults entries
* are purged silently
*/
void
verifyRemoval()
{
Symbol pID ("some_pipe");
Query<Pipe> query_for_pID ("pipe("+pID+")");
size_t hash;
{
// create new pipe and declare it to be a default
PPipe pipe1 = Struct::retrieve.newInstance<Pipe> (pID);
Session::current->defaults.define(pipe1);
CHECK (2 == pipe1.use_count()); // the pipe1 smart-ptr and the AssetManager
hash = pipe1->getID();
}
// pipe1 out of scope....
// AssetManager now should hold the only ref
ID<Asset> assetID (hash);
AssetManager& aMang (AssetManager::instance());
CHECK ( aMang.known (assetID));
aMang.remove (assetID);
CHECK (!aMang.known (assetID));
CHECK (!find(query_for_pID)); // bare default-query should fail...
PPipe pipe2 = Session::current->defaults (query_for_pID); // triggers re-creation
CHECK ( find(query_for_pID)); // should succeed again
}
};
/** Register this test class... */
LAUNCHER (DefsManager_test, "function session");
}} // namespace asset::test

View file

@ -1,296 +0,0 @@
/*
DefsRegistryImpl(Test) - verifying correct behaviour of the defaults registry
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/util.hpp"
#include "proc/mobject/session/defsregistry.hpp"
#include "lib/factory.hpp"
#include "lib/query.hpp"
#include "lib/p.hpp"
#include "../lib/query/querydiagnostics.hpp"
#include <boost/scoped_ptr.hpp>
#include <boost/format.hpp>
#include <map>
using lumiera::P;
using lumiera::Query;
using lumiera::query::test::garbage_query;
using util::isnil;
using boost::scoped_ptr;
using boost::format;
using std::string;
using std::rand;
using std::map;
namespace mobject {
namespace session {
namespace test {
format typePatt ("Dummy<%2i>");
format instancePatt ("obj_%s_%i");
format predicatePatt ("%s_%2i( %s )");
/** create a random new ID */
string
newID (string prefix)
{
return str (instancePatt % prefix % rand());
}
/** template for generating some different test types */
template<int I>
struct Dummy
{
static string name;
string instanceID;
operator string () const { return instanceID; }
bool operator== (const Dummy& odu) const { return this == &odu; }
Dummy () : instanceID (newID (name)) {}
};
template<int I>
string Dummy<I>::name = str (typePatt % I);
/************************************************************************
* @test build an registry table (just for this test) configured for
* some artificial test Types. Register some entries and verify
* the intended behaviour of the storage structure.
* @see DefsManagerImpl_test for checking the implementation details
* in the actual context used in Lumiera.
*/
class DefsRegistryImpl_test : public Test
{
scoped_ptr<DefsRegistry> reg_;
typedef lumiera::P<Dummy<13> > O;
typedef lumiera::P<Dummy<23> > P;
typedef Query<Dummy<13> > Q13;
typedef Query<Dummy<23> > Q23;
typedef DefsRegistry::Iter<Dummy<13> > Iter13;
typedef DefsRegistry::Iter<Dummy<23> > Iter23;
// fabricating Objects wrapped into smart-ptrs
lib::factory::RefcountFac<Dummy<13> > oFac;
lib::factory::RefcountFac<Dummy<23> > pFac;
O o1, o2, o3;
Q13 q1, q2, q3, q4, q5;
map<Q23, P> ps;
public:
DefsRegistryImpl_test ()
: o1 (oFac()), o2 (oFac()), o3 (oFac()),
q1 (garbage_query (1)),
q2 (garbage_query (2)),
q3 (garbage_query (3)),
q4 (garbage_query (4)),
q5 (garbage_query (5))
{ }
virtual void
run (Arg)
{
this->reg_.reset (new DefsRegistry);
fill_table ();
check_query ();
check_remove ();
}
void
fill_table ()
{
// at start the registry is indeed empty
// thus a query doesn't yield any results....
CHECK ( ! *(reg_->candidates(Q13 ("something"))) );
reg_->put (o1, q5);
reg_->put (o2, q4);
reg_->put (o3, q3);
reg_->put (o3, q2);
reg_->put (o2, q1);
reg_->put (o1, Q13()); // the empty query
ps.clear();
for (int i=0; i<100; ++i)
{
P px (pFac());
Q23 qx (garbage_query());
ps[qx] = px;
reg_->put (px, qx);
px->instanceID = qx;
}
}
void
check_query ()
{
Iter13 i (reg_->candidates(Q13 ("irrelevant query")));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i == o1);
CHECK (!i.hasNext());
CHECK (! *++i ); // null after end
i = reg_->candidates(q3);
CHECK ( *i++ == o3); // found by direct match
CHECK ( *i++ == o1); // followed by the ordered enumeration
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
i = reg_->candidates(Q13());
CHECK ( *i++ == o1); // found by direct match to the empty query
CHECK ( *i++ == o1);
CHECK ( *i++ == o2);
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
CHECK ( *i++ == o2);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
uint d=0;
uint d_prev=0;
Iter23 j = reg_->candidates(Q23 ("some crap"));
for ( ; *j ; ++j )
{
CHECK ( *j );
Q23 qx ((*j)->instanceID);
CHECK ( ps[qx] == (*j));
d = lumiera::query::countPred (qx);
CHECK ( d_prev <= d );
d_prev = d;
}
CHECK (!j.hasNext());
// calling with an arbitrary (registered) query
// yields the corresponding object at start of the enumeration
j = reg_->candidates(ps.begin()->first);
CHECK ( *j == ps.begin()->second);
}
void
check_remove ()
{
reg_->forget (o2);
Iter13 i (reg_->candidates(q4));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
// but the o2 entries are missing
CHECK ( *i++ == o3);
CHECK ( *i++ == o3);
// missing
CHECK ( *i == o1);
CHECK (!i.hasNext());
o3.reset(); // killing the only reference....
// expires the weak ref in the registry
i = reg_->candidates(Q13 ("something"));
CHECK ( i.hasNext());
CHECK ( *i++ == o1); // ordered according to the degree of the queries
// but now also the o3 entries are missing...
CHECK ( *i == o1);
CHECK (!i.hasNext());
CHECK ( reg_->put (o1, q5)); // trying to register the same object at the same place
// doesn't change anything (but counts as "success")
i = reg_->candidates(q5);
CHECK ( *i++ == o1); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK (!reg_->put (o2, q5)); // trying to (re)register o2 with a existing query
// counts as failure (nothing changes)
i = reg_->candidates(q5);
CHECK ( *i++ == o1); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK ( reg_->put (o2, q2)); // trying to (re)register o2 with another query succeeds
i = reg_->candidates(q2);
CHECK ( *i++ == o2); // direct match
CHECK ( *i++ == o1);
CHECK ( *i++ == o2); // inserted here in the dataset
CHECK ( *i++ == o1);
CHECK (!i.hasNext());
CHECK ( reg_->forget (o1));
CHECK (!reg_->forget (o1)); // failure, because it's already removed
CHECK ( reg_->forget (o2));
o3 = oFac(); // another object is another object (it's irrelevant...)
i = reg_->candidates(q2);
CHECK (! (*i)); // empty
}
};
/** Register this test class... */
LAUNCHER (DefsRegistryImpl_test, "function session");
} // namespace test
} // namespace mobject
} // namespace mobject

View file

@ -43,7 +43,7 @@ test_lib_SOURCES = \
$(testlib_srcdir)/advice/advice-index-test.cpp \
$(testlib_srcdir)/advice/advice-multiplicity-test.cpp \
$(testlib_srcdir)/advice/advice-situations-test.cpp \
$(testlib_srcdir)/allocationclustertest.cpp \
$(testlib_srcdir)/allocation-cluster-test.cpp \
$(testlib_srcdir)/appconfigtest.cpp \
$(testlib_srcdir)/bool-checkable-test.cpp \
$(testlib_srcdir)/custom-shared-ptr-test.cpp \
@ -87,7 +87,7 @@ test_lib_SOURCES = \
$(testlib_srcdir)/scoped-holder-transfer-test.cpp \
$(testlib_srcdir)/singleton-subclass-test.cpp \
$(testlib_srcdir)/singleton-test.cpp \
$(testlib_srcdir)/singletontestmocktest.cpp \
$(testlib_srcdir)/singleton-testmock-test.cpp \
$(testlib_srcdir)/streamtypebasicstest.cpp \
$(testlib_srcdir)/streamtypelifecycletest.cpp \
$(testlib_srcdir)/sub-id-test.cpp \

View file

@ -0,0 +1,234 @@
/*
AllocationCluster(Test) - verify bulk (de)allocating a family of objects
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/util-foreach.hpp"
#include "lib/allocation-cluster.hpp"
#include "lib/scoped-holder.hpp"
#include <vector>
#include <limits>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using lib::test::showSizeof;
using util::for_each;
using util::isnil;
using ::Test;
using std::numeric_limits;
using std::vector;
namespace lib {
namespace test {
namespace { // a family of test dummy classes
uint NUM_CLUSTERS = 5;
uint NUM_OBJECTS = 500;
uint NUM_FAMILIES = 5;
long checksum = 0; // validate proper pairing of ctor/dtor calls
bool randomFailures = false;
template<uint i>
class Dummy
{
char content[i];
public:
Dummy (char id=1)
{
content[0] = id;
checksum += id;
}
Dummy (char i1, char i2, char i3=0)
{
char id = i1 + i2 + i3;
content[0] = id;
checksum += id;
if (randomFailures && 0 == (rand() % 20))
throw id;
}
~Dummy()
{
checksum -= content[0];
}
char getID() { return content[0]; }
};
typedef ScopedHolder<AllocationCluster> PCluster;
typedef vector<PCluster> ClusterList;
inline char
truncChar (uint x)
{
return x % numeric_limits<char>::max();
}
template<uint i>
void
place_object (AllocationCluster& clu, uint id)
{
clu.create<Dummy<i> > (id);
}
typedef void (Invoker)(AllocationCluster&, uint);
Invoker* invoke[20] = { &place_object<1>
, &place_object<2>
, &place_object<3>
, &place_object<5>
, &place_object<10>
, &place_object<13>
, &place_object<14>
, &place_object<15>
, &place_object<16>
, &place_object<17>
, &place_object<18>
, &place_object<19>
, &place_object<20>
, &place_object<25>
, &place_object<30>
, &place_object<35>
, &place_object<40>
, &place_object<50>
, &place_object<100>
, &place_object<200>
};
void
fillIt (PCluster& clu)
{
clu.create();
if (20<NUM_FAMILIES)
NUM_FAMILIES = 20;
for (uint i=0; i<NUM_OBJECTS; ++i)
{
char id = truncChar(i);
(*(invoke[rand() % NUM_FAMILIES])) (*clu,id);
}
}
}
/*************************************************************************
* @test verify the proper workings of our custom allocation scheme
* managing families of interconnected objects for the segments
* of the low-level model.
*/
class AllocationCluster_test : public Test
{
virtual void
run (Arg arg)
{
if (0 < arg.size()) NUM_CLUSTERS = lexical_cast<uint> (arg[0]);
if (1 < arg.size()) NUM_OBJECTS = lexical_cast<uint> (arg[1]);
if (2 < arg.size()) NUM_FAMILIES = lexical_cast<uint> (arg[2]);
simpleUsage();
checkAllocation();
checkErrorHandling();
}
void
simpleUsage()
{
AllocationCluster clu;
char c1(123), c2(56), c3(3), c4(4), c5(5);
Dummy<44>& ref1 = clu.create<Dummy<44> > ();
Dummy<37>& ref2 = clu.create<Dummy<37> > (c1);
Dummy<37>& ref3 = clu.create<Dummy<37> > (c2);
Dummy<1234>& rX = clu.create<Dummy<1234> > (c3,c4,c5);
CHECK (&ref1);
CHECK (&ref2);
CHECK (&ref3);
CHECK (&rX);
TRACE (test, "%s", showSizeof(rX).c_str());
CHECK (123==ref2.getID());
CHECK (3+4+5==rX.getID());
// shows that the returned references actually
// point at the objects we created. Just use them
// and let them go. When clu goes out of scope,
// all created object's dtors will be invoked.
}
void
checkAllocation()
{
CHECK (0==checksum);
{
ClusterList clusters (NUM_CLUSTERS);
for_each (clusters, fillIt);
CHECK (0!=checksum);
}
CHECK (0==checksum);
}
void
checkErrorHandling()
{
CHECK (0==checksum);
{
randomFailures = true;
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
try
{
char i1 = truncChar(i);
char i2 = truncChar(rand() % 5);
clu.create<Dummy<1> > (i1,i2);
}
catch (char id)
{
checksum -= id; // exception thrown from within constructor,
} // thus dtor won't be called. Repair the checksum!
}
randomFailures = false;
CHECK (0==checksum);
}
};
LAUNCHER (AllocationCluster_test, "unit common");
}} // namespace lib::test

View file

@ -1,236 +0,0 @@
/*
AllocationCluster(Test) - verify bulk (de)allocating a family of objects
Copyright (C) Lumiera.org
2008, 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.
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/util-foreach.hpp"
#include "lib/allocationcluster.hpp"
#include "lib/scoped-holder.hpp"
#include <vector>
#include <limits>
#include <boost/lexical_cast.hpp>
using boost::lexical_cast;
using lib::test::showSizeof;
using util::for_each;
using util::isnil;
using ::Test;
using std::numeric_limits;
using std::vector;
namespace lib {
namespace test {
namespace { // a family of test dummy classes
uint NUM_CLUSTERS = 5;
uint NUM_OBJECTS = 500;
uint NUM_FAMILIES = 5;
long checksum = 0; // validate proper pairing of ctor/dtor calls
bool randomFailures = false;
template<uint i>
class Dummy
{
char content[i];
public:
Dummy (char id=1)
{
content[0] = id;
checksum += id;
}
Dummy (char i1, char i2, char i3=0)
{
char id = i1 + i2 + i3;
content[0] = id;
checksum += id;
if (randomFailures && 0 == (rand() % 20))
throw id;
}
~Dummy()
{
checksum -= content[0];
}
char getID() { return content[0]; }
};
typedef ScopedHolder<AllocationCluster> PCluster;
typedef vector<PCluster> ClusterList;
inline char
truncChar (uint x)
{
return x % numeric_limits<char>::max();
}
template<uint i>
void
place_object (AllocationCluster& clu, uint id)
{
clu.create<Dummy<i> > (id);
}
typedef void (Invoker)(AllocationCluster&, uint);
Invoker* invoke[20] = { &place_object<1>
, &place_object<2>
, &place_object<3>
, &place_object<5>
, &place_object<10>
, &place_object<13>
, &place_object<14>
, &place_object<15>
, &place_object<16>
, &place_object<17>
, &place_object<18>
, &place_object<19>
, &place_object<20>
, &place_object<25>
, &place_object<30>
, &place_object<35>
, &place_object<40>
, &place_object<50>
, &place_object<100>
, &place_object<200>
};
void
fillIt (PCluster& clu)
{
clu.create();
if (20<NUM_FAMILIES)
NUM_FAMILIES = 20;
for (uint i=0; i<NUM_OBJECTS; ++i)
{
char id = truncChar(i);
(*(invoke[rand() % NUM_FAMILIES])) (*clu,id);
}
}
}
/*************************************************************************
* @test verify the proper workings of our custom allocation scheme
* managing families of interconnected objects for the segments
* of the low-level model.
*/
class AllocationCluster_test : public Test
{
virtual void
run (Arg arg)
{
if (0 < arg.size()) NUM_CLUSTERS = lexical_cast<uint> (arg[0]);
if (1 < arg.size()) NUM_OBJECTS = lexical_cast<uint> (arg[1]);
if (2 < arg.size()) NUM_FAMILIES = lexical_cast<uint> (arg[2]);
simpleUsage();
checkAllocation();
checkErrorHandling();
}
void
simpleUsage()
{
AllocationCluster clu;
char c1(123), c2(56), c3(3), c4(4), c5(5);
Dummy<44>& ref1 = clu.create<Dummy<44> > ();
Dummy<37>& ref2 = clu.create<Dummy<37> > (c1);
Dummy<37>& ref3 = clu.create<Dummy<37> > (c2);
Dummy<1234>& rX = clu.create<Dummy<1234> > (c3,c4,c5);
CHECK (&ref1);
CHECK (&ref2);
CHECK (&ref3);
CHECK (&rX);
TRACE (test, "%s", showSizeof(rX).c_str());
CHECK (123==ref2.getID());
CHECK (3+4+5==rX.getID());
// shows that the returned references actually
// point at the objects we created. Just use them
// and let them go. When clu goes out of scope,
// all created object's dtors will be invoked.
}
void
checkAllocation()
{
CHECK (0==checksum);
{
ClusterList clusters (NUM_CLUSTERS);
for_each (clusters, fillIt);
CHECK (0!=checksum);
}
CHECK (0==checksum);
}
void
checkErrorHandling()
{
CHECK (0==checksum);
{
randomFailures = true;
AllocationCluster clu;
for (uint i=0; i<NUM_OBJECTS; ++i)
try
{
char i1 = truncChar(i);
char i2 = truncChar(rand() % 5);
clu.create<Dummy<1> > (i1,i2);
}
catch (char id)
{
checksum -= id; // exception thrown from within constructor,
} // thus dtor won't be called. Repair the checksum!
}
randomFailures = false;
CHECK (0==checksum);
}
};
LAUNCHER (AllocationCluster_test, "unit common");
}// namespace test
} // namespace lib

View file

@ -85,7 +85,9 @@ namespace lib {
typedef typename std::vector<HOL,Allo> Type;
};
}
}//(End) test helpers
@ -232,7 +234,4 @@ namespace lib {
LAUNCHER (ScopedHolderTransfer_test, "unit common");
}// namespace test
} // namespace lib
}} // namespace lib::test

View file

@ -78,7 +78,7 @@ namespace test{
*
* @see CommandRegistry
* @see command-registry-test.cpp
* @see allocationclustertest.cpp
* @see allocation-cluster-test.cpp
*/
class TypedAllocationManager_test : public Test
{

View file

@ -97,6 +97,7 @@ namespace lib {
};
void
transfer_control (TransDummy& from, TransDummy& to)
{
@ -157,7 +158,4 @@ namespace lib {
LAUNCHER (VectorTransfer_test, "unit common");
}// namespace test
} // namespace lib
}} // namespace lib::test