some naming cleanup and namespace indentation fixes
This commit is contained in:
parent
3f1b7651e9
commit
7fc462209e
39 changed files with 1732 additions and 1741 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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>
|
||||
|
|
@ -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"
|
||||
138
src/lib/singleton-policies.hpp
Normal file
138
src/lib/singleton-policies.hpp
Normal 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
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#define LUMIERA_TEST_MOCKINJECTOR_H
|
||||
|
||||
|
||||
#include "lib/singletonfactory.hpp"
|
||||
#include "lib/singleton-factory.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
128
src/proc/mobject/session/defs-manager.hpp
Normal file
128
src/proc/mobject/session/defs-manager.hpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
176
tests/components/proc/mobject/session/defs-manager-impl-test.cpp
Normal file
176
tests/components/proc/mobject/session/defs-manager-impl-test.cpp
Normal 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
|
||||
204
tests/components/proc/mobject/session/defs-manager-test.cpp
Normal file
204
tests/components/proc/mobject/session/defs-manager-test.cpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 \
|
||||
|
|
|
|||
234
tests/lib/allocation-cluster-test.cpp
Normal file
234
tests/lib/allocation-cluster-test.cpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue