WIP: correct indentation, add some comments...
This commit is contained in:
parent
99310dc0af
commit
209765def5
5 changed files with 405 additions and 398 deletions
|
|
@ -31,12 +31,12 @@
|
|||
** to generate, filter and process those configurations. The final goal is to
|
||||
** automatically generate a factory which is able to deliver objects
|
||||
** configured according to the situation encoded in the flags.
|
||||
**
|
||||
**
|
||||
** @note currently there is an inherent limitation to configurations defined by
|
||||
** a maximum of 5 independent flags. While it is easy to increase this limit,
|
||||
** you should consider that the final goal is to generate template instantiations,
|
||||
** which would lead to more and more code bloat with growing number of possible
|
||||
** combination.
|
||||
** combinations.
|
||||
**
|
||||
** @see proc::engine::config::Strategy usage example
|
||||
** @see proc::engine::config::ConfigSelector
|
||||
|
|
@ -53,153 +53,151 @@
|
|||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist {
|
||||
|
||||
const size_t CONFIG_FLAGS_MAX = 5;
|
||||
|
||||
|
||||
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 typelist::Config<Fl,f1,f2,f3,f4> Config;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** build a configuration type from a list-of-flags */
|
||||
template<class FLAGS, class CONF=typelist::Config<> >
|
||||
struct BuildConfigFromFlags
|
||||
{
|
||||
typedef CONF Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
template<char Fl, class FLAGS, class CONF>
|
||||
struct BuildConfigFromFlags< Node<Flag<Fl>,FLAGS>, CONF>
|
||||
{
|
||||
typedef typename ConfigSetFlag< Fl
|
||||
, typename BuildConfigFromFlags<FLAGS,CONF>::Config
|
||||
>::Config Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
|
||||
/** create a configuration type for the given list-of-flags */
|
||||
template<class FLAGS>
|
||||
struct DefineConfigByFlags : BuildConfigFromFlags<FLAGS> { };
|
||||
|
||||
|
||||
namespace {
|
||||
/** helper comparing enum values and chars (flags) */
|
||||
template<char ii, char jj>
|
||||
struct maxC
|
||||
{
|
||||
enum{ VAL = ii < jj? jj : ii };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 enumerating 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 visitation 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 = maxC< ff, FlagInfo<FLAGS>::BITS> ::VAL
|
||||
, 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 = maxC< FlagInfo<ThisFlags>::BITS, FlagInfo<TAIL>::BITS > ::VAL
|
||||
};
|
||||
|
||||
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 typelist{
|
||||
|
||||
} // namespace lumiera
|
||||
const size_t CONFIG_FLAGS_MAX = 5;
|
||||
|
||||
|
||||
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 typelist::Config<Fl,f1,f2,f3,f4> Config;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** build a configuration type from a list-of-flags */
|
||||
template<class FLAGS, class CONF=typelist::Config<> >
|
||||
struct BuildConfigFromFlags
|
||||
{
|
||||
typedef CONF Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
template<char Fl, class FLAGS, class CONF>
|
||||
struct BuildConfigFromFlags< Node<Flag<Fl>,FLAGS>, CONF>
|
||||
{
|
||||
typedef typename ConfigSetFlag< Fl
|
||||
, typename BuildConfigFromFlags<FLAGS,CONF>::Config
|
||||
>::Config Config;
|
||||
typedef Config Type;
|
||||
};
|
||||
|
||||
/** create a configuration type for the given list-of-flags */
|
||||
template<class FLAGS>
|
||||
struct DefineConfigByFlags : BuildConfigFromFlags<FLAGS> { };
|
||||
|
||||
|
||||
namespace {
|
||||
/** helper comparing enum values and chars (flags) */
|
||||
template<char ii, char jj>
|
||||
struct maxC
|
||||
{
|
||||
enum{ VAL = ii < jj? jj : ii };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 enumerating 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 visitation 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 = maxC< ff, FlagInfo<FLAGS>::BITS> ::VAL
|
||||
, 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 = maxC< FlagInfo<ThisFlags>::BITS, FlagInfo<TAIL>::BITS > ::VAL
|
||||
};
|
||||
|
||||
template<class FUNC>
|
||||
static typename FUNC::Ret
|
||||
accept (FUNC& functor)
|
||||
{
|
||||
functor.template visit<CONF>(FlagInfo<ThisFlags>::CODE);
|
||||
return FlagInfo<TAIL>::accept (functor);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace lumiera::typelist
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
** and enables to pull a result frames from the nodes. Especially, the aspect of
|
||||
** buffer management and cache query is covered here. Each node has been preconfigured by
|
||||
** the builder with a WiringDescriptor and a concrete type of a StateAdapter, including
|
||||
** a specific Configuration, because the node can be built to
|
||||
** a specific Configuration, because the node can be built to
|
||||
** - participate in the Caching or ignore the cache
|
||||
** - actually process a result or just pull frames from a source
|
||||
** - employ in-Place calculations or use separate in/out buffers
|
||||
|
|
@ -42,15 +42,15 @@
|
|||
** configurations are pre-built while compiling (it's a small number below 32 configuration instance).
|
||||
** To be able to select the Strategy for each configuration, we need a Factory (ConfigSelector defined in
|
||||
** nodewiring-config.hpp). which is actually instantiated and used in nodewiring.cpp, which is the object
|
||||
** file holding all those instantiations.
|
||||
**
|
||||
** file holding all those instantiations.
|
||||
**
|
||||
** @see engine::ProcNode
|
||||
** @see engine::Invocation
|
||||
** @see engine::State
|
||||
** @see engine::NodeFactory
|
||||
** @see nodewiring-config.hpp
|
||||
** @see nodewiring.hpp interface for building/wiring the nodes
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef ENGINE_NODEOPERATION_H
|
||||
|
|
@ -71,249 +71,249 @@
|
|||
|
||||
|
||||
namespace engine {
|
||||
namespace config {
|
||||
|
||||
|
||||
/**
|
||||
* Base class of all concrete invocation sequences.
|
||||
* Could contain a collection of functions used to build up the invocation sequence.
|
||||
* Currently contains just a marker used to detect the existence of an concrete
|
||||
* definition/specialisation for a given specific configuration.
|
||||
*/
|
||||
class OperationBase
|
||||
{
|
||||
typedef lumiera::Yes_t is_defined;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct QueryCache : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle fetched = ivo.fetch (ivo.genFrameID());
|
||||
if (fetched)
|
||||
return fetched;
|
||||
else
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct AllocBufferTable : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffTableChunk buffTab (ivo.wiring, ivo.getBuffTableStorage());
|
||||
ivo.setBuffTab(&buffTab);
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.buffTab_isConsistent());
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct PullInput : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle * inH = ivo.buffTab->inHandle;
|
||||
BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff;
|
||||
|
||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
||||
{
|
||||
inBuff[i] =
|
||||
*(inH[i] = this->pullPredecessor(ivo,i)); // invoke predecessor
|
||||
// now Input #i is ready...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct ReadSource : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle *inH = ivo.buffTab->inHandle;
|
||||
BuffHandle *outH = ivo.buffTab->outHandle;
|
||||
BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff;
|
||||
BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff;
|
||||
|
||||
ASSERT (ivo.nrO() == ivo.nrI() );
|
||||
|
||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
||||
{
|
||||
inBuff[i] = outBuff[i] =
|
||||
*(inH[i] = outH[i] = this->getSource(ivo,i));
|
||||
// now Input #i is ready...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct AllocOutput : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.nrO() < ivo.buffTabSize());
|
||||
BuffHandle *outH = ivo.buffTab->outHandle;
|
||||
BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff;
|
||||
|
||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
||||
{
|
||||
outBuff[i] =
|
||||
*(outH[i] = ivo.allocateBuffer (ivo.wiring.out[i].bufferType));
|
||||
// now Output buffer for channel #i is available...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct ProcessData : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.buffTab_isConsistent());
|
||||
ASSERT (this->validateBuffers(ivo));
|
||||
|
||||
// Invoke our own process() function,
|
||||
// providing the array of outBuffer+inBuffer ptrs
|
||||
ivo.wiring.procFunction (ivo.buffTab->outBuff);
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NEXT>
|
||||
struct FeedCache : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
||||
{
|
||||
// declare all Outputs as finished
|
||||
ivo.is_calculated(ivo.buffTab->outHandle[i]);
|
||||
}
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NEXT>
|
||||
struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor??
|
||||
{ ///////////////// this would require BuffHandle to be a smart ref....
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
// all buffers besides the required Output no longer needed
|
||||
this->releaseBuffers(ivo.buffTab->outHandle,
|
||||
ivo.buffTabSize(),
|
||||
ivo.outNr);
|
||||
|
||||
return ivo.buffTab->outHandle[ivo.outNr];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* =============================================================== */
|
||||
/* === 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;
|
||||
|
||||
template<> struct SelectBuffProvider<CACHING> { typedef AllocBufferFromCache Type; };
|
||||
template<> struct SelectBuffProvider<NOT_SET,INPLACE> { typedef AllocBufferFromParent Type; };
|
||||
template<> struct SelectBuffProvider<CACHING,INPLACE> { typedef AllocBufferFromCache Type; };
|
||||
template<> struct SelectBuffProvider<> { typedef AllocBufferFromParent Type; };
|
||||
namespace config {
|
||||
|
||||
|
||||
template<class Config>
|
||||
struct Strategy ;
|
||||
|
||||
using lumiera::typelist::Config;
|
||||
|
||||
template<char INPLACE>
|
||||
struct Strategy< Config<CACHING,PROCESS,INPLACE> >
|
||||
: QueryCache<
|
||||
AllocBufferTable<
|
||||
PullInput<
|
||||
AllocOutput<
|
||||
ProcessData<
|
||||
FeedCache<
|
||||
ReleaseBuffers<
|
||||
OperationBase > > > > > > >
|
||||
{ };
|
||||
|
||||
template<char INPLACE>
|
||||
struct Strategy< Config<PROCESS,INPLACE> >
|
||||
: AllocBufferTable<
|
||||
PullInput<
|
||||
AllocOutput<
|
||||
ProcessData<
|
||||
/**
|
||||
* Base class of all concrete invocation sequences.
|
||||
* Could contain a collection of functions used to build up the invocation sequence.
|
||||
* Currently contains just a marker used to detect the existence of an concrete
|
||||
* definition/specialisation for a given specific configuration.
|
||||
*/
|
||||
class OperationBase
|
||||
{
|
||||
typedef lumiera::Yes_t is_defined;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct QueryCache : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle fetched = ivo.fetch (ivo.genFrameID());
|
||||
if (fetched)
|
||||
return fetched;
|
||||
else
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct AllocBufferTable : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffTableChunk buffTab (ivo.wiring, ivo.getBuffTableStorage());
|
||||
ivo.setBuffTab(&buffTab);
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.buffTab_isConsistent());
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct PullInput : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle * inH = ivo.buffTab->inHandle;
|
||||
BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff;
|
||||
|
||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
||||
{
|
||||
inBuff[i] =
|
||||
*(inH[i] = this->pullPredecessor(ivo,i)); // invoke predecessor
|
||||
// now Input #i is ready...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct ReadSource : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
BuffHandle *inH = ivo.buffTab->inHandle;
|
||||
BuffHandle *outH = ivo.buffTab->outHandle;
|
||||
BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff;
|
||||
BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff;
|
||||
|
||||
ASSERT (ivo.nrO() == ivo.nrI() );
|
||||
|
||||
for (uint i = 0; i < ivo.nrI(); ++i )
|
||||
{
|
||||
inBuff[i] = outBuff[i] =
|
||||
*(inH[i] = outH[i] = this->getSource(ivo,i));
|
||||
// now Input #i is ready...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct AllocOutput : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.nrO() < ivo.buffTabSize());
|
||||
BuffHandle *outH = ivo.buffTab->outHandle;
|
||||
BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff;
|
||||
|
||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
||||
{
|
||||
outBuff[i] =
|
||||
*(outH[i] = ivo.allocateBuffer (ivo.wiring.out[i].bufferType));
|
||||
// now Output buffer for channel #i is available...
|
||||
}
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class NEXT>
|
||||
struct ProcessData : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
ASSERT (ivo.buffTab);
|
||||
ASSERT (ivo.buffTab_isConsistent());
|
||||
ASSERT (this->validateBuffers(ivo));
|
||||
|
||||
// Invoke our own process() function,
|
||||
// providing the array of outBuffer+inBuffer ptrs
|
||||
ivo.wiring.procFunction (ivo.buffTab->outBuff);
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NEXT>
|
||||
struct FeedCache : NEXT
|
||||
{
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
for (uint i = 0; i < ivo.nrO(); ++i )
|
||||
{
|
||||
// declare all Outputs as finished
|
||||
ivo.is_calculated(ivo.buffTab->outHandle[i]);
|
||||
}
|
||||
|
||||
return NEXT::step (ivo);
|
||||
}
|
||||
};
|
||||
|
||||
template<class NEXT>
|
||||
struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor??
|
||||
{ ///////////////// this would require BuffHandle to be a smart ref....
|
||||
BuffHandle
|
||||
step (Invocation& ivo)
|
||||
{
|
||||
// all buffers besides the required Output no longer needed
|
||||
this->releaseBuffers(ivo.buffTab->outHandle,
|
||||
ivo.buffTabSize(),
|
||||
ivo.outNr);
|
||||
|
||||
return ivo.buffTab->outHandle[ivo.outNr];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* =============================================================== */
|
||||
/* === declare the possible Assembly of these elementary steps === */
|
||||
|
||||
enum Cases
|
||||
{
|
||||
CACHING = 1,
|
||||
PROCESS,
|
||||
INPLACE,
|
||||
|
||||
NOT_SET = 0,
|
||||
NUM_Cases = INPLACE
|
||||
};
|
||||
|
||||
|
||||
|
||||
template< char CACHE_Fl =NOT_SET
|
||||
, char INPLACE_Fl =NOT_SET
|
||||
>
|
||||
struct SelectBuffProvider;
|
||||
|
||||
template<> struct SelectBuffProvider<CACHING> { typedef AllocBufferFromCache Type; };
|
||||
template<> struct SelectBuffProvider<NOT_SET,INPLACE> { typedef AllocBufferFromParent Type; };
|
||||
template<> struct SelectBuffProvider<CACHING,INPLACE> { typedef AllocBufferFromCache Type; };
|
||||
template<> struct SelectBuffProvider<> { typedef AllocBufferFromParent Type; };
|
||||
|
||||
|
||||
template<class Config>
|
||||
struct Strategy ;
|
||||
|
||||
using lumiera::typelist::Config;
|
||||
|
||||
template<char INPLACE>
|
||||
struct Strategy< Config<CACHING,PROCESS,INPLACE> >
|
||||
: QueryCache<
|
||||
AllocBufferTable<
|
||||
PullInput<
|
||||
AllocOutput<
|
||||
ProcessData<
|
||||
FeedCache<
|
||||
ReleaseBuffers<
|
||||
OperationBase > > > > >
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct Strategy< Config<> >
|
||||
: AllocBufferTable<
|
||||
ReadSource<
|
||||
OperationBase > > > > > > >
|
||||
{ };
|
||||
|
||||
template<char INPLACE>
|
||||
struct Strategy< Config<PROCESS,INPLACE> >
|
||||
: AllocBufferTable<
|
||||
PullInput<
|
||||
AllocOutput<
|
||||
ProcessData<
|
||||
ReleaseBuffers<
|
||||
OperationBase > > >
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct Strategy< Config<INPLACE> > : Strategy< Config<> > { };
|
||||
|
||||
template<>
|
||||
struct Strategy< Config<CACHING> >
|
||||
: AllocBufferTable<
|
||||
ReadSource<
|
||||
AllocOutput<
|
||||
ProcessData< // wiring_.processFunction is supposed to do just buffer copying here
|
||||
ReleaseBuffers<
|
||||
OperationBase > > > > >
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace config
|
||||
OperationBase > > > > >
|
||||
{ };
|
||||
|
||||
} // namespace engine
|
||||
template<>
|
||||
struct Strategy< Config<> >
|
||||
: AllocBufferTable<
|
||||
ReadSource<
|
||||
ReleaseBuffers<
|
||||
OperationBase > > >
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct Strategy< Config<INPLACE> > : Strategy< Config<> > { };
|
||||
|
||||
template<>
|
||||
struct Strategy< Config<CACHING> >
|
||||
: AllocBufferTable<
|
||||
ReadSource<
|
||||
AllocOutput<
|
||||
ProcessData< // wiring_.processFunction is supposed to do just buffer copying here
|
||||
ReleaseBuffers<
|
||||
OperationBase > > > > >
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
|
||||
}} // namespace engine::config
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ namespace config {
|
|||
{
|
||||
FactoryHolder(PAR p)
|
||||
: FAC(p),
|
||||
FacFunction( static_cast<FAC&>(*this))
|
||||
FacFunction (static_cast<FAC&> (*this))
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
@ -127,7 +127,9 @@ namespace config {
|
|||
|
||||
ConfigTable possibleConfig_; ///< Table of factories
|
||||
|
||||
/** Helper: a visitor usable with FlagInfo */
|
||||
|
||||
/** Helper: a visitor usable with FlagInfo.
|
||||
* Used to create a factory for each config */
|
||||
struct FactoryTableBuilder
|
||||
{
|
||||
PAR ctor_param_;
|
||||
|
|
@ -153,6 +155,7 @@ namespace config {
|
|||
void done() {}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
template<class CONFS>
|
||||
ConfigSelector(CONFS const&, PAR factory_ctor_param)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ namespace engine {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* Fabricating a WiringDescriptor
|
||||
* tailored for a specific node wiring situation.
|
||||
*/
|
||||
template<class CONF>
|
||||
class WiringDescriptorFactory
|
||||
{
|
||||
|
|
@ -138,3 +142,4 @@ namespace engine {
|
|||
|
||||
|
||||
} // namespace engine
|
||||
/** preconfigured table of all possible factories */
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ namespace test {
|
|||
|
||||
struct TestVisitor
|
||||
{
|
||||
string result;
|
||||
string result; ///< metafunction result
|
||||
|
||||
TestVisitor() : result ("TestVisitor application:\n") {}
|
||||
|
||||
/* === visitation interface === */
|
||||
|
|
@ -319,7 +320,7 @@ namespace test {
|
|||
catch (lumiera::error::Invalid& err)
|
||||
{
|
||||
cout << err.what() << "\n";
|
||||
lumiera_error (); // reset errorflag
|
||||
lumiera_error (); // reset error flag
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue