WIP rearranged some headers
This commit is contained in:
parent
276ac8e082
commit
847cc9c267
16 changed files with 535 additions and 409 deletions
|
|
@ -48,7 +48,7 @@
|
|||
|
||||
#include "common/p.hpp"
|
||||
#include "common/query.hpp"
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
#include "common/singletonsubclass.hpp"
|
||||
|
||||
//TODO: is it sensible to bring in the types explicitly here? (it's not necessary, but may be convenient...)
|
||||
|
|
|
|||
180
src/common/meta/configflags.hpp
Normal file
180
src/common/meta/configflags.hpp
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
CONFIGFLAGS.hpp - Building classes based on configuration cases
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file configflags.hpp
|
||||
** Under some circumstances it is necessary to assemble functionality
|
||||
** out of elementary building blocks. Especially, this assembly can be
|
||||
** expressed as template specialisations directed by a configuration type.
|
||||
** Thus, the purpose of this header is to encode a flag-like configuraiton
|
||||
** as distinct types, which can be used to select such specialisations.
|
||||
** Each possible configuration can be encoded as a list of flags, which allows
|
||||
** to generate, filter and process those configurations. The final goal is to
|
||||
** automatically generate a factory which will deliver objects configured
|
||||
** according to the configuration in question.
|
||||
**
|
||||
** @see proc::engine::config::Strategy usage example
|
||||
** @see proc::engine::config::ConfigSelector
|
||||
** @see typelist.hpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LUMIERA_META_CONFIGFLAGS_H
|
||||
#define LUMIERA_META_CONFIGFLAGS_H
|
||||
|
||||
|
||||
#include "common/meta/typelist.hpp"
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist {
|
||||
|
||||
|
||||
template<char bit> struct Flag { typedef Flag ID; };
|
||||
template<> struct Flag<0> { typedef NullType ID; };
|
||||
|
||||
|
||||
template< char f1=0
|
||||
, char f2=0
|
||||
, char f3=0
|
||||
, char f4=0
|
||||
, char f5=0
|
||||
>
|
||||
struct Flags
|
||||
{
|
||||
typedef typename Types< typename Flag<f1>::ID
|
||||
, typename Flag<f2>::ID
|
||||
, typename Flag<f3>::ID
|
||||
, typename Flag<f4>::ID
|
||||
, typename Flag<f5>::ID
|
||||
>::List
|
||||
Tuple;
|
||||
typedef Tuple List;
|
||||
};
|
||||
|
||||
|
||||
template< char f1=0
|
||||
, char f2=0
|
||||
, char f3=0
|
||||
, char f4=0
|
||||
, char f5=0
|
||||
>
|
||||
struct Config ///< distinct type representing a configuration
|
||||
{
|
||||
typedef typename Flags<f1,f2,f3,f4,f5>::Tuple Flags;
|
||||
typedef Flags List;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<char Fl, class CONF>
|
||||
struct ConfigSetFlag; ///< set (prepend) the Flag to the given config
|
||||
|
||||
template< char Fl
|
||||
, char f1
|
||||
, char f2
|
||||
, char f3
|
||||
, char f4
|
||||
, char IGN
|
||||
>
|
||||
struct ConfigSetFlag<Fl, Config<f1,f2,f3,f4,IGN> >
|
||||
{
|
||||
typedef Config<Fl,f1,f2,f3,f4> Config;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** build a configuration type for the given list-of-flags */
|
||||
template<class FLAGS, class CONF=Config<> >
|
||||
struct DefineConfigByFlags
|
||||
{
|
||||
typedef CONF Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
template<char Fl, class FLAGS, class CONF>
|
||||
struct DefineConfigByFlags< Node<Flag<Fl>,FLAGS>, CONF>
|
||||
{
|
||||
typedef typename ConfigSetFlag< Fl
|
||||
, typename DefineConfigByFlags<FLAGS,CONF>::Config
|
||||
>::Config Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for calculating values and for
|
||||
* invoking runtime code based on a given FlagTuple.
|
||||
* Can also be used on a Typelist of several Configs.
|
||||
* The latter case is typically used to invoke an operation
|
||||
* while ennumerating all Flag-Configurations defined in Code.
|
||||
* An example would be to build (at runtime) an dispatcher table.
|
||||
* Explanation: For the Case covering a List of Configs, we provide
|
||||
* a templated visitaion function, which can accept a functor object
|
||||
* to be invoked on each Configuration.
|
||||
*/
|
||||
template<class FLAGS>
|
||||
struct FlagInfo;
|
||||
|
||||
template<char ff, class FLAGS>
|
||||
struct FlagInfo<Node<Flag<ff>, FLAGS> >
|
||||
{
|
||||
enum{ BITS = MAX(ff, FlagInfo<FLAGS>::BITS)
|
||||
, CODE = (1<<ff) | FlagInfo<FLAGS>::CODE
|
||||
};
|
||||
};
|
||||
template<>
|
||||
struct FlagInfo<NullType>
|
||||
{
|
||||
enum{ BITS = 0
|
||||
, CODE = 0
|
||||
};
|
||||
|
||||
template<class FUNC>
|
||||
static typename FUNC::Ret
|
||||
accept (FUNC& functor)
|
||||
{
|
||||
return functor.done();
|
||||
}
|
||||
};
|
||||
template<class CONF, class TAIL>
|
||||
struct FlagInfo<Node<CONF, TAIL> >
|
||||
{
|
||||
typedef typename CONF::Flags ThisFlags;
|
||||
enum{ BITS = MAX (char(FlagInfo<ThisFlags>::BITS), char(FlagInfo<TAIL>::BITS))
|
||||
};
|
||||
|
||||
template<class FUNC>
|
||||
static typename FUNC::Ret
|
||||
accept (FUNC& functor)
|
||||
{
|
||||
functor.template visit<CONF>(FlagInfo<ThisFlags>::CODE);
|
||||
return FlagInfo<TAIL>::accept (functor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TYPELISTUTIL.hpp - metaprogramming utilities for lists-of-types
|
||||
GENERATOR.hpp - metaprogramming utilities for generating classes and interfaces
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -38,7 +38,7 @@ This code is heavily inspired by
|
|||
*/
|
||||
|
||||
|
||||
/** @file typelistutil.hpp
|
||||
/** @file generator.hpp
|
||||
** Helpers for working with lumiera::typelist::Types (i.e. lists-of-types).
|
||||
** The main purpose is to build interfaces and polymorphic implementations
|
||||
** (using virtual functions) based on templated Types or Collections of types,
|
||||
|
|
@ -50,10 +50,10 @@ This code is heavily inspired by
|
|||
*/
|
||||
|
||||
|
||||
#ifndef LUMIERA_TYPELISTUTIL_H
|
||||
#define LUMIERA_TYPELISTUTIL_H
|
||||
#ifndef LUMIERA_META_GENERATOR_H
|
||||
#define LUMIERA_META_GENERATOR_H
|
||||
|
||||
#include "common/typelist.hpp"
|
||||
#include "common/meta/typelist.hpp"
|
||||
|
||||
|
||||
|
||||
|
|
@ -196,42 +196,6 @@ namespace lumiera
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction counting the number of Types in the collection
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct count;
|
||||
template<>
|
||||
struct count<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct count<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ value = 1 + count<TYPES>::value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Metafunction " max( sizeof(T) ) for T in TYPES "
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct maxSize;
|
||||
template<>
|
||||
struct maxSize<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct maxSize<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ thisval = sizeof(TY)
|
||||
, nextval = maxSize<TYPES>::value
|
||||
, value = nextval > thisval? nextval:thisval
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
|
|
@ -53,8 +53,8 @@ This code is heavily inspired by
|
|||
*/
|
||||
|
||||
|
||||
#ifndef LUMIERA_TYPELIST_H
|
||||
#define LUMIERA_TYPELIST_H
|
||||
#ifndef LUMIERA_META_TYPELIST_H
|
||||
#define LUMIERA_META_TYPELIST_H
|
||||
|
||||
|
||||
|
||||
213
src/common/meta/typelistutil.hpp
Normal file
213
src/common/meta/typelistutil.hpp
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
TYPELISTUTIL.hpp - Utils for working with lists-of-types
|
||||
|
||||
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 LUMIERA_META_TYPELISTUTIL_H
|
||||
#define LUMIERA_META_TYPELISTUTIL_H
|
||||
|
||||
|
||||
|
||||
#include "common/meta/typelist.hpp"
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist {
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction counting the number of Types in the collection
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct count;
|
||||
template<>
|
||||
struct count<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct count<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ value = 1 + count<TYPES>::value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Metafunction " max( sizeof(T) ) for T in TYPES "
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct maxSize;
|
||||
template<>
|
||||
struct maxSize<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct maxSize<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ thisval = sizeof(TY)
|
||||
, nextval = maxSize<TYPES>::value
|
||||
, value = nextval > thisval? nextval:thisval
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** apply a transformation (template) to each type in the list */
|
||||
template<class TY, template<class> class _TRANS_>
|
||||
struct Apply { typedef TY List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _TRANS_
|
||||
>
|
||||
struct Apply<Node<TY,TYPES>, _TRANS_ > { typedef Node< typename _TRANS_<TY>::Type
|
||||
, typename Apply<TYPES,_TRANS_>::List
|
||||
> List; };
|
||||
|
||||
|
||||
template<bool, class T, class TAIL>
|
||||
struct CondNode { typedef TAIL Next; };
|
||||
|
||||
template<class T, class TAIL>
|
||||
struct CondNode<true, T, TAIL> { typedef Node<T,TAIL> Next; };
|
||||
|
||||
/** filter away those types which don't fulfill a predicate metafunction */
|
||||
template< class TYPES
|
||||
, template<class> class _P_ ///< a template providing a boolean member \c ::value
|
||||
>
|
||||
struct Filter;
|
||||
|
||||
template<template<class> class _P_>
|
||||
struct Filter<NullType,_P_> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _P_
|
||||
>
|
||||
struct Filter<Node<TY,TYPES>,_P_> { typedef typename CondNode< _P_<TY>::value
|
||||
, TY
|
||||
, typename Filter<TYPES,_P_>::List
|
||||
>::Next
|
||||
List; };
|
||||
|
||||
|
||||
/** append lists-of-types */
|
||||
template<class TY1, class TY2>
|
||||
struct Append { typedef Node<TY1, typename Append<TY2,NullType>::List> List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Append<Node<TY,TYPES>, TAIL> { typedef Node<TY, typename Append<TYPES, TAIL>::List> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<NullType, Node<TY,TYPES> > { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<Node<TY,TYPES>, NullType> { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY1>
|
||||
struct Append<TY1,NullType> { typedef Node<TY1,NullType> List; };
|
||||
|
||||
template<class TY2>
|
||||
struct Append<NullType,TY2> { typedef Node<TY2,NullType> List; };
|
||||
|
||||
template<>
|
||||
struct Append<NullType,NullType> { typedef NullType List; };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* prefix each of the elements,
|
||||
* yielding a list-of lists-of-types
|
||||
*/
|
||||
template<class T, class TY>
|
||||
struct PrefixAll { typedef Node< typename Append<T,TY>::List, NullType> List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NullType> { typedef NullType List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NodeNull> { typedef Node< typename Append<T,NodeNull>::List, NullType> List; };
|
||||
|
||||
template< class T
|
||||
, class TY, class TYPES
|
||||
>
|
||||
struct PrefixAll<T, Node<TY,TYPES> > { typedef Node< typename Append<T,TY>::List
|
||||
, typename PrefixAll<T,TYPES>::List
|
||||
> List; };
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TY1,class TY2>
|
||||
struct Distribute { typedef typename PrefixAll<TY1,TY2>::List List; };
|
||||
|
||||
template<class TY>
|
||||
struct Distribute<NullType,TY> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Distribute<Node<TY,TYPES>,TAIL> { typedef typename Append< typename PrefixAll<TY,TAIL>::List
|
||||
, typename Distribute<TYPES,TAIL>::List
|
||||
>::List
|
||||
List; };
|
||||
|
||||
|
||||
|
||||
/** use a permutation generator
|
||||
* for creating a list of all possible combinations
|
||||
*/
|
||||
template< class X
|
||||
, template<class> class _PERMU_>
|
||||
struct Combine { typedef typename Distribute< typename _PERMU_<X>::List
|
||||
, Node<NullType,NullType>
|
||||
>::List List; };
|
||||
template< template<class> class _PERMU_>
|
||||
struct Combine<NullType, _PERMU_ > { typedef Node<NullType,NullType> List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _PERMU_>
|
||||
struct Combine<Node<TY,TYPES>,_PERMU_> { typedef typename Distribute< typename _PERMU_<TY>::List
|
||||
, typename Combine<TYPES,_PERMU_>::List
|
||||
>::List List; };
|
||||
|
||||
/** permutation generator for the Combine metafunction,
|
||||
* yielding an "on" and "off" case
|
||||
*/
|
||||
template<class F>
|
||||
struct FlagOnOff
|
||||
{
|
||||
typedef Node<F, Node<NullType,NullType> > List;
|
||||
};
|
||||
|
||||
|
||||
/** generate all possible on-off combinations of the given flags */
|
||||
template<class FLAGS>
|
||||
struct CombineFlags
|
||||
{
|
||||
typedef typename Combine<FLAGS, FlagOnOff>::List List;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
74
src/common/meta/util.hpp
Normal file
74
src/common/meta/util.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
UTIL.hpp - metaprogramming helpers and utilities
|
||||
|
||||
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 LUMIERA_META_UTIL_H
|
||||
#define LUMIERA_META_UTIL_H
|
||||
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist {
|
||||
|
||||
|
||||
/* types for figuring out the overload resolution chosen by the compiler */
|
||||
|
||||
typedef char Yes_t;
|
||||
struct No_t { char padding[8]; };
|
||||
|
||||
|
||||
/** semi-automatic detection if an instantiation is possible.
|
||||
* Requires help by the template to be tested, which needs to define
|
||||
* a typedef member \c is_defined. The embedded metafunction Test can be used
|
||||
* as a predicate for filtering types which may yield a valid instantiation
|
||||
* of the candidate template in question.
|
||||
* \par
|
||||
* A fully automated solution for this problem is impossible by theoretic reasons.
|
||||
* Any non trivial use of such a \c is_defined trait would break the "One Definition Rule",
|
||||
* as the state of any type can change from "partially defined" to "fully defined" over
|
||||
* the course of any translation unit. Thus, even if there may be a \em solution out there,
|
||||
* we can expect it to break at some point by improvements/fixes to the C++ Language.
|
||||
*/
|
||||
template<template<class> class _CandidateTemplate_>
|
||||
struct Instantiation
|
||||
{
|
||||
|
||||
template<class X>
|
||||
class Test
|
||||
{
|
||||
typedef _CandidateTemplate_<X> Instance;
|
||||
|
||||
template<class U>
|
||||
static Yes_t check(typename U::is_defined *);
|
||||
template<class U>
|
||||
static No_t check(...);
|
||||
|
||||
public:
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<Instance>(0)));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
#define LUMIERA_VARIANT_H
|
||||
|
||||
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ Credits for many further implementation ideas go to
|
|||
#include "common/visitorpolicies.hpp"
|
||||
#include "common/visitordispatcher.hpp"
|
||||
|
||||
#include "common/typelist.hpp"
|
||||
#include "common/meta/typelist.hpp"
|
||||
|
||||
|
||||
namespace lumiera
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "common/variant.hpp"
|
||||
#include "common/accesscasted.hpp"
|
||||
|
||||
#include "common/typelist.hpp"
|
||||
#include "common/meta/typelist.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "common/p.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@
|
|||
#include "proc/engine/buffhandle.hpp"
|
||||
#include "proc/engine/bufftable.hpp"
|
||||
#include "proc/engine/nodeinvocation.hpp"
|
||||
#include "proc/engine/nodewiringconfig.hpp"
|
||||
|
||||
|
||||
|
||||
|
|
@ -230,6 +229,18 @@ namespace engine {
|
|||
|
||||
/* === declare the possible Assembly of these elementary steps === */
|
||||
|
||||
enum Cases
|
||||
{
|
||||
CACHING = 1,
|
||||
PROCESS,
|
||||
INPLACE,
|
||||
|
||||
NOT_SET = 0,
|
||||
NUM_Cases = INPLACE
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<char CACHE_Fl=0, char INPLACE_Fl=0>
|
||||
struct SelectBuffProvider;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,369 +19,49 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file nodewiringconfig.hpp
|
||||
** Sometimes we need to coose a different implementation for dealing with
|
||||
** some special cases. While for simple cases, just testing a flag or using a
|
||||
** switch statement will do the job, matters get more difficult when we have to
|
||||
** employ a completely different execution path for each of the different cases,
|
||||
** while using a set of common building blocks.
|
||||
** \par
|
||||
** In the Lumiera render engine, right on the critical path, we need some glue code
|
||||
** for invoking the predecessor nodes when pulling a given processing node. The actual
|
||||
** sequence is quite dependant on the specific situation each node is wired up, regarding
|
||||
** buffer allocation, cache querying and the possible support for GPU processing and
|
||||
** render farms. The solution is to define specialisations of a Strategy template
|
||||
** using the specific configuration as template argument. Based on these, we can
|
||||
** create a collection of factories, which in turn will build the internal wiring
|
||||
** for the individual ProcNode instances in accordance to the situation determined
|
||||
** for this node, expressed as a set of flags. As a net result, each node has an
|
||||
** indivudual configuration (as opposed to creating a lot of hand-written individual
|
||||
** ProcNode subclasses), but parts of this configuration assembly is done already at
|
||||
** compile time, allowing for additional checks by typing and for possible optimisation.
|
||||
**
|
||||
** @see proc::engine::config::Strategy
|
||||
** @see nodewiring.hpp
|
||||
** @see configflags.hpp
|
||||
**
|
||||
*/
|
||||
#ifndef ENGINE_NODEWIRINGCONFIG_H
|
||||
#define ENGINE_NODEWIRINGCONFIG_H
|
||||
|
||||
|
||||
#include "common/util.hpp"
|
||||
#include "common/meta/configflags.hpp"
|
||||
|
||||
//#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
/////////////////TODO: library
|
||||
|
||||
#include "common/typelistutil.hpp"
|
||||
namespace lumiera {
|
||||
namespace typelist {
|
||||
|
||||
template<class TY, template<class> class _TRANS_>
|
||||
struct Apply { typedef TY List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _TRANS_
|
||||
>
|
||||
struct Apply<Node<TY,TYPES>, _TRANS_ > { typedef Node< typename _TRANS_<TY>::Type
|
||||
, typename Apply<TYPES,_TRANS_>::List
|
||||
> List; };
|
||||
|
||||
|
||||
template<bool, class T, class TAIL>
|
||||
struct CondNode { typedef TAIL Next; };
|
||||
|
||||
template<class T, class TAIL>
|
||||
struct CondNode<true, T, TAIL> { typedef Node<T,TAIL> Next; };
|
||||
|
||||
|
||||
template< class TYPES , template<class> class _P_>
|
||||
struct Filter;
|
||||
|
||||
template<template<class> class _P_>
|
||||
struct Filter<NullType,_P_> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _P_
|
||||
>
|
||||
struct Filter<Node<TY,TYPES>,_P_> { typedef typename CondNode< _P_<TY>::value
|
||||
, TY
|
||||
, typename Filter<TYPES,_P_>::List
|
||||
>::Next
|
||||
List; };
|
||||
|
||||
|
||||
|
||||
template<class TY1, class TY2>
|
||||
struct Append { typedef Node<TY1, typename Append<TY2,NullType>::List> List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Append<Node<TY,TYPES>, TAIL> { typedef Node<TY, typename Append<TYPES, TAIL>::List> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<NullType, Node<TY,TYPES> > { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<Node<TY,TYPES>, NullType> { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY1>
|
||||
struct Append<TY1,NullType> { typedef Node<TY1,NullType> List; };
|
||||
|
||||
template<class TY2>
|
||||
struct Append<NullType,TY2> { typedef Node<TY2,NullType> List; };
|
||||
|
||||
template<>
|
||||
struct Append<NullType,NullType> { typedef NullType List; };
|
||||
|
||||
|
||||
|
||||
|
||||
template<class T, class TY>
|
||||
struct PrefixAll { typedef Node< typename Append<T,TY>::List, NullType> List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NullType> { typedef NullType List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NodeNull> { typedef Node< typename Append<T,NodeNull>::List, NullType> List; };
|
||||
|
||||
template< class T
|
||||
, class TY, class TYPES
|
||||
>
|
||||
struct PrefixAll<T, Node<TY,TYPES> > { typedef Node< typename Append<T,TY>::List
|
||||
, typename PrefixAll<T,TYPES>::List
|
||||
> List; };
|
||||
|
||||
|
||||
|
||||
|
||||
template<class TY1,class TY2>
|
||||
struct Distribute { typedef typename PrefixAll<TY1,TY2>::List List; };
|
||||
|
||||
template<class TY>
|
||||
struct Distribute<NullType,TY> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Distribute<Node<TY,TYPES>,TAIL> { typedef typename Append< typename PrefixAll<TY,TAIL>::List
|
||||
, typename Distribute<TYPES,TAIL>::List
|
||||
>::List
|
||||
List; };
|
||||
|
||||
|
||||
|
||||
|
||||
template< class X
|
||||
, template<class> class _PERMU_>
|
||||
struct Combine { typedef typename Distribute< typename _PERMU_<X>::List
|
||||
, Node<NullType,NullType>
|
||||
>::List List; };
|
||||
template< template<class> class _PERMU_>
|
||||
struct Combine<NullType, _PERMU_ > { typedef Node<NullType,NullType> List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _PERMU_>
|
||||
struct Combine<Node<TY,TYPES>,_PERMU_> { typedef typename Distribute< typename _PERMU_<TY>::List
|
||||
, typename Combine<TYPES,_PERMU_>::List
|
||||
>::List List; };
|
||||
|
||||
|
||||
template<class F>
|
||||
struct FlagOnOff
|
||||
{
|
||||
typedef Node<F, Node<NullType,NullType> > List;
|
||||
};
|
||||
|
||||
template<class FLAGS>
|
||||
struct CombineFlags
|
||||
{
|
||||
typedef typename Combine<FLAGS, FlagOnOff>::List List;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/////////// meta utils
|
||||
|
||||
typedef char Yes_t;
|
||||
struct No_t { char padding[8]; };
|
||||
|
||||
|
||||
/** semi-automatic detection if an instantiation is possible.
|
||||
* Requires help by the template to be tested, which needs to define
|
||||
* a typedef member \c is_defined. The embedded metafunction Test can be used
|
||||
* as a predicate for filtering types which may yield a valid instantiation
|
||||
* of the candidate template in question.
|
||||
* \par
|
||||
* A fully automated solution for this problem is impossible by theoretic reasons.
|
||||
* Any non trivial use of such a \c is_defined trait would break the "One Definition Rule",
|
||||
* as the state of any type can change from "partially defined" to "fully defined" over
|
||||
* the course of any translation unit. Thus, even if there may be a \em solution out there,
|
||||
* we can expect it to break at some point by improvements/fixes to the C++ Language.
|
||||
*/
|
||||
template<template<class> class _CandidateTemplate_>
|
||||
struct Instantiation
|
||||
{
|
||||
|
||||
template<class X>
|
||||
class Test
|
||||
{
|
||||
typedef _CandidateTemplate_<X> Instance;
|
||||
|
||||
template<class U>
|
||||
static Yes_t check(typename U::is_defined *);
|
||||
template<class U>
|
||||
static No_t check(...);
|
||||
|
||||
public:
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<Instance>(0)));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<char bit> struct Flag { typedef Flag ID; };
|
||||
template<> struct Flag<0> { typedef NullType ID; };
|
||||
|
||||
|
||||
template< char f1=0
|
||||
, char f2=0
|
||||
, char f3=0
|
||||
, char f4=0
|
||||
, char f5=0
|
||||
>
|
||||
struct Flags
|
||||
{
|
||||
typedef typename Types< typename Flag<f1>::ID
|
||||
, typename Flag<f2>::ID
|
||||
, typename Flag<f3>::ID
|
||||
, typename Flag<f4>::ID
|
||||
, typename Flag<f5>::ID
|
||||
>::List
|
||||
Tuple;
|
||||
typedef Tuple List;
|
||||
};
|
||||
|
||||
|
||||
template< char f1=0
|
||||
, char f2=0
|
||||
, char f3=0
|
||||
, char f4=0
|
||||
, char f5=0
|
||||
>
|
||||
struct Config
|
||||
{
|
||||
typedef typename Flags<f1,f2,f3,f4,f5>::Tuple Flags;
|
||||
typedef Flags List;
|
||||
};
|
||||
|
||||
|
||||
template<char Fl, class CONF>
|
||||
struct ConfigSetFlag;
|
||||
|
||||
template< char Fl
|
||||
, char f1
|
||||
, char f2
|
||||
, char f3
|
||||
, char f4
|
||||
, char IGN
|
||||
>
|
||||
struct ConfigSetFlag<Fl, Config<f1,f2,f3,f4,IGN> >
|
||||
{
|
||||
typedef Config<Fl,f1,f2,f3,f4> Config;
|
||||
};
|
||||
|
||||
template<class FLAGS, class CONF=Config<> >
|
||||
struct DefineConfigByFlags
|
||||
{
|
||||
typedef CONF Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
template<char Fl, class FLAGS, class CONF>
|
||||
struct DefineConfigByFlags< Node<Flag<Fl>,FLAGS>, CONF>
|
||||
{
|
||||
typedef typename ConfigSetFlag< Fl
|
||||
, typename DefineConfigByFlags<FLAGS,CONF>::Config
|
||||
>::Config Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper for calculating values and for
|
||||
* invoking runtime code based on a given FlagTuple.
|
||||
* Can also be used on a Typelist of several Configs.
|
||||
* The latter case is typically used to invoke an operation
|
||||
* while ennumerating all Flag-Configurations defined in Code.
|
||||
* An example would be to build (at runtime) an dispatcher table.
|
||||
* Explanation: For the Case covering a List of Configs, we provide
|
||||
* a templated visitaion function, which can accept a functor object
|
||||
* to be invoked on each Configuration.
|
||||
*/
|
||||
template<class FLAGS>
|
||||
struct FlagInfo;
|
||||
|
||||
template<char ff, class FLAGS>
|
||||
struct FlagInfo<Node<Flag<ff>, FLAGS> >
|
||||
{
|
||||
enum{ BITS = MAX(ff, FlagInfo<FLAGS>::BITS)
|
||||
, CODE = (1<<ff) | FlagInfo<FLAGS>::CODE
|
||||
};
|
||||
};
|
||||
template<>
|
||||
struct FlagInfo<NullType>
|
||||
{
|
||||
enum{ BITS = 0
|
||||
, CODE = 0
|
||||
};
|
||||
|
||||
template<class FUNC>
|
||||
static typename FUNC::Ret
|
||||
accept (FUNC& functor)
|
||||
{
|
||||
return functor.done();
|
||||
}
|
||||
};
|
||||
template<class CONF, class TAIL>
|
||||
struct FlagInfo<Node<CONF, TAIL> >
|
||||
{
|
||||
typedef typename CONF::Flags ThisFlags;
|
||||
enum{ BITS = MAX (char(FlagInfo<ThisFlags>::BITS), char(FlagInfo<TAIL>::BITS))
|
||||
};
|
||||
|
||||
template<class FUNC>
|
||||
static typename FUNC::Ret
|
||||
accept (FUNC& functor)
|
||||
{
|
||||
functor.template visit<CONF>(FlagInfo<ThisFlags>::CODE);
|
||||
return FlagInfo<TAIL>::accept (functor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
|
||||
/////////////////TODO: library(end)
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace engine {
|
||||
|
||||
|
||||
class WiringFactory;
|
||||
|
||||
///////TODO
|
||||
using lumiera::typelist::Config;
|
||||
using lumiera::typelist::FlagInfo;
|
||||
using lumiera::typelist::DefineConfigByFlags;
|
||||
///////TODO
|
||||
|
||||
using boost::lexical_cast;
|
||||
using util::contains;
|
||||
|
||||
enum Cases
|
||||
{
|
||||
CACHING = 1,
|
||||
PROCESS,
|
||||
INPLACE,
|
||||
|
||||
NOT_SET = 0,
|
||||
NUM_Cases = INPLACE
|
||||
};
|
||||
typedef std::bitset<NUM_Cases> Bits;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper type used to describe the \em situation on which to base
|
||||
* the selection of the wiring and configuration of a ProcNode.
|
||||
* It is based on a tuple of elementary parameters (here of type bool);
|
||||
* a combination of these describes the situation and is used to select
|
||||
* a strategy, which in turn determines what concret operations to use
|
||||
* while pulling the node, and how to combine these operations.
|
||||
* @see engine::Strategy ///TODO namespace....
|
||||
*/
|
||||
// template<bool caching, bool process, bool inplace>
|
||||
// struct Config
|
||||
// {
|
||||
// static Bits getRepr () { return getCaseRepresentation(caching,process,inplace); }
|
||||
// };
|
||||
|
||||
|
||||
/**
|
||||
* Helper for fabricating ProcNode Wiring configurations.
|
||||
|
|
@ -439,7 +119,7 @@ namespace engine {
|
|||
};
|
||||
|
||||
|
||||
typedef boost::shared_ptr<FacFunctor> PFunc;
|
||||
typedef std::tr1::shared_ptr<FacFunctor> PFunc;
|
||||
typedef std::map<size_t, PFunc> ConfigTable;
|
||||
|
||||
ConfigTable possibleConfig_; ///< Table of factories
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ using boost::is_base_of;
|
|||
#include <boost/type_traits/is_polymorphic.hpp>
|
||||
|
||||
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
using lumiera::typelist::NullType;
|
||||
using lumiera::typelist::Node;
|
||||
using lumiera::typelist::Types;
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@
|
|||
|
||||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
#include "common/meta/typelistutil.hpp"
|
||||
#include "proc/engine/nodewiringconfig.hpp"
|
||||
#include "common/util.hpp"
|
||||
//#include "common/typelist/typelistmanip.hpp"
|
||||
#include "proc/engine/nodewiringconfig.hpp" ///////////TODO move to configflags.hpp
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -343,6 +343,10 @@ namespace lumiera {
|
|||
};
|
||||
|
||||
|
||||
/** @test use the ConfigSelector template to build a set of factories,
|
||||
* based on a set of configurations. Then invoke the apropriate
|
||||
* factory by specifying the configuration bit code
|
||||
*/
|
||||
void check_ConfigSelector()
|
||||
{
|
||||
cout << "\n==== check_ConfigSelector()\n";
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TypeListUtil(Test) - check the typelist helpers
|
||||
Generator(Test) - build an interface + implementation directed by a typelis
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
* *****************************************************/
|
||||
|
||||
|
||||
/** @file typelistutiltest.cpp
|
||||
/** @file generatortest.cpp
|
||||
** \par what are we doing here??
|
||||
**
|
||||
** the following test composes both an interface and the corresponding implementation
|
||||
|
|
@ -31,14 +31,14 @@
|
|||
** need to be absolutely fixed in the class definition)
|
||||
**
|
||||
** @see typelisttest.cpp
|
||||
** @see typelistutil.hpp
|
||||
** @see generator.hpp
|
||||
** @see lumiera::query::ConfigRules a real world usage example
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -118,7 +118,7 @@ namespace lumiera
|
|||
* for a collection of classes</li>
|
||||
* </ul>
|
||||
*/
|
||||
class TypeListUtil_test : public Test
|
||||
class TypeListGenerator_test : public Test
|
||||
{
|
||||
virtual void run(Arg arg)
|
||||
{
|
||||
|
|
@ -144,7 +144,7 @@ namespace lumiera
|
|||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (TypeListUtil_test, "unit common");
|
||||
LAUNCHER (TypeListGenerator_test, "unit common");
|
||||
|
||||
|
||||
|
||||
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/meta/generator.hpp"
|
||||
#include "common/meta/typelistutil.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "proc/engine/nodewiringconfig.hpp" ///////////TODO move to typelistutil.hpp
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
|
||||
#include "common/test/run.hpp"
|
||||
#include "common/typelist.hpp"
|
||||
#include "common/meta/typelist.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Loading…
Reference in a new issue