/* * Scheduler.hh * * Created on: Dec 3, 2012 * Author: f.casimir */ #ifndef Scheduler_HH_ #define Scheduler_HH_ #include "vector" #include <boost/algorithm/string.hpp> #include "AMDA_exception.hh" #include "DicError.hh" #include "Parameter.hh" #include "ParamData.hh" #include "Operation.hh" using namespace std; using namespace boost; using namespace AMDA::Parameters; namespace AMDA { namespace Merge { /** * name space of base class, implementation are template class */ namespace Base { /** * @brief abstract class can write in paramDatas output * @details is the strategy interface in the Strategy pattern * the implementation arc made by template Pusher class */ class Pusher { public: virtual ~Pusher() {} virtual void write(unsigned int /*index*/) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_ERROR_UNKNOWN) << AMDA::ex_msg("Pusher operation not supported")); } }; /** * @brief the operation of MergeProcess * @detail write one line by paramData input * The implementation are made by template class. */ class Scheduler : public Operation { public: /** * @brief Constructor */ Scheduler(Process& pProcess) : Operation(pProcess) {} /** * @brief Destructor */ virtual ~Scheduler() { for(auto operation : _operationList) { delete operation; } } /** * @brief add an input paramData */ virtual void push_back(ParamData*) = 0; protected: /** * @brief store a Base::Pusher by ParamDataInput */ std::vector<Base::Pusher*> _operationList; }; } // Base; /** * Definition of Pucher class template */ template<typename ParamOutput, typename ParamInput> class Pusher : public Base::Pusher { public: /** * @brief Constructor */ Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} private: /** * @brief paramData Output */ ParamOutput& _paramOutput; /** * @brief paramData Input */ ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput and ParamInput are ParamDataSpec<std::vector<ElType> with ElType are standard C++ type as float */ template<typename ElType1, typename ElType2> class Pusher<ParamDataSpec<std::vector<ElType1> >,ParamDataSpec<std::vector<ElType2> > > : public Base::Pusher { public: typedef ParamDataSpec<std::vector<ElType1> > ParamOutput; typedef ParamDataSpec<std::vector<ElType2> > ParamInput; /** * @brief Constructor */ Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} /** * @overload operation::write(unsigned int index) */ void write(unsigned int index) { _paramOutput.pushTime(_paramInput.getTime(index)); const std::vector<ElType2>& lData = _paramInput.getDataList()[index]; _paramOutput.getDataList().push_back(std::vector<ElType1>(lData.begin(),lData.end())); } private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput and ParamInput are ParamDataSpec<std::vector<LogicalData> */ template<> class Pusher<ParamDataSpec<std::vector<LogicalData> >,ParamDataSpec<std::vector<LogicalData> > > : public Base::Pusher { public: typedef ParamDataSpec<std::vector<LogicalData> > ParamOutput; typedef ParamDataSpec<std::vector<LogicalData> > ParamInput; /** * @brief Constructor */ Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} /** * @overload operation::write(unsigned int index) */ void write(unsigned int index) { _paramOutput.pushTime(_paramInput.getTime(index)); _paramOutput.getDataList().push_back(_paramInput.getDataList()[index]); } private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput are ParamDataSpec<std::vector<LogicalData> * and ParamInput are ParamDataSpec<std::vector<ElType> with ElType are standard C++ type as float * throw an exception if use @see Base::Pusher::write() */ template<typename ElType2> class Pusher<ParamDataSpec<std::vector<LogicalData> >,ParamDataSpec<std::vector<ElType2> > > : public Base::Pusher { public: typedef ParamDataSpec<std::vector<LogicalData> > ParamOutput; typedef ParamDataSpec<std::vector<ElType2> > ParamInput; /** * @brief Constructor */ Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput are ParamDataSpec<std::vector<ElType> with ElType are standard C++ type as float * and ParamInput are ParamDataSpec<std::vector<LogicalData> * throw an exception if use @see Base::Pusher::write() */ template<typename ElType1> class Pusher<ParamDataSpec<std::vector<ElType1> >,ParamDataSpec<std::vector<LogicalData> > > : public Base::Pusher { public: typedef ParamDataSpec<std::vector<ElType1> > ParamOutput; typedef ParamDataSpec<std::vector<LogicalData> > ParamInput; Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput and ParamInput are ParamDataSpec<std::vector<ElType> with ElType are standard C++ type as float */ template<typename ElType> class Pusher<ParamDataSpec<std::vector<ElType> >,ParamDataSpec<std::vector<ElType> > > : public Base::Pusher { public: typedef ParamDataSpec<std::vector<ElType> > ParamOutput; typedef ParamDataSpec<std::vector<ElType> > ParamInput; /** * @brief Constructor */ Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} /** * @overload operation::write(unsigned int index) */ void write(unsigned int index) { _paramOutput.pushTime(_paramInput.getTime(index)); _paramOutput.getDataList().push_back(_paramInput.getDataList()[index]); } private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput and ParamInput are ParamDataSpec<ElType> with ElType are standard C++ type as float */ template<typename ElType> class Pusher<ParamDataSpec<ElType>,ParamDataSpec<ElType> > : public Base::Pusher { public: typedef ParamDataSpec<ElType> ParamOutput; typedef ParamDataSpec<ElType> ParamInput; Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} /** * @overload operation::write(unsigned int index) */ void write(unsigned int index) { _paramOutput.pushTime(_paramInput.getTime(index)); _paramOutput.getDataList().push_back(_paramInput.getDataList()[index]); } private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput is is ParamDataSpec<LogicalData> * and ParamInput is any * throw an exception if use @see Base::Pusher::write() */ template<typename TParamInput> class Pusher<ParamDataSpec<LogicalData>,TParamInput> : public Base::Pusher { public: typedef ParamDataSpec<LogicalData> ParamOutput; typedef TParamInput ParamInput; Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput is any * and ParamInput are ParamDataSpec<LogicalData> * throw an exception if use @see Base::Pusher::write() */ template<typename TParamOutput> class Pusher<TParamOutput,ParamDataSpec<LogicalData> > : public Base::Pusher { public: typedef TParamOutput ParamOutput; typedef ParamDataSpec<LogicalData> ParamInput; Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief vector implementation of Pusher template * @detail ParamOutput and ParamInput are ParamDataSpec<LogicalData> * throw an exception if use @see Base::Pusher::write() */ template<> class Pusher<ParamDataSpec<LogicalData>,ParamDataSpec<LogicalData> > : public Base::Pusher { public: typedef ParamDataSpec<LogicalData> ParamOutput; typedef ParamDataSpec<LogicalData> ParamInput; Pusher(ParamOutput& pParamOutput, ParamInput& pParamInput) : _paramOutput(pParamOutput), _paramInput(pParamInput) {} /** * @overload operation::write(unsigned int index) */ void write(unsigned int index) { _paramOutput.pushTime(_paramInput.getTime(index)); _paramOutput.getDataList().push_back(_paramInput.getDataList()[index]); } private: ParamOutput& _paramOutput; ParamInput& _paramInput; }; /** * @brief Create the specific Pusher class * @details used the visitor pattern for find the good Pusher in function of ParamInput type */ template<typename TParamOutput> class PusherCreator : public VisitorOfParamData { public: /** * @brief Constructor. */ PusherCreator(TParamOutput& pOutputParamData,ParamData& pInputParamData) : _outputParamData(pOutputParamData), _operation(nullptr) { pInputParamData.accept(*this); } /** * @overload VisitorOfParamData::visit(ParamDataScalaireShort *) */ void visit(ParamDataScalaireShort *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataScalaireShort>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataScalaireFloat *) */ void visit(ParamDataScalaireFloat *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataScalaireFloat>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataScalaireDouble *) */ void visit(ParamDataScalaireDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataScalaireDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataScalaireLongDouble *) */ void visit(ParamDataScalaireLongDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataScalaireLongDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataScalaireInt *) */ void visit(ParamDataScalaireInt *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataScalaireInt>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataLogicalData *) */ void visit(ParamDataLogicalData *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataLogicalData>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DShort *) */ void visit(ParamDataTab1DShort *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DShort>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DFloat *) */ void visit(ParamDataTab1DFloat *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DFloat>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DDouble *) */ void visit(ParamDataTab1DDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DLongDouble *) */ void visit(ParamDataTab1DLongDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DLongDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DInt *) */ void visit(ParamDataTab1DInt *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DInt>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab1DLogicalData *) */ void visit(ParamDataTab1DLogicalData *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab1DLogicalData>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DShort *) */ void visit(ParamDataTab2DShort *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DShort>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DFloat *) */ void visit(ParamDataTab2DFloat *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DFloat>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DDouble *) */ void visit(ParamDataTab2DDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DLongDouble *) */ void visit(ParamDataTab2DLongDouble *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DLongDouble>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DInt *) */ void visit(ParamDataTab2DInt *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DInt>( _outputParamData,*pInputParamData); } /** * @overload VisitorOfParamData::visit(ParamDataTab2DLogicalData *) */ void visit(ParamDataTab2DLogicalData *pInputParamData) { _operation = new Pusher<TParamOutput,ParamDataTab2DLogicalData>( _outputParamData,*pInputParamData); } Base::Pusher *getPusher() { return _operation; } private: TParamOutput &_outputParamData; Base::Pusher *_operation; }; /** * @brief Base::Scheduler implementation */ template<typename TParamOutput> class Scheduler : public Base::Scheduler { public: Scheduler(Process& pProcess) : Base::Scheduler(pProcess), _paramOutput(new TParamOutput()) { _paramDataOutput=_paramOutput; } /** * @overload Base::Scheduler::write(ParamDataIndexInfo &pParamDataIndexInfo) */ void push_back(ParamData* pInputParam) { PusherCreator<TParamOutput> lPusherCreator(*_paramOutput,*pInputParam); _operationList.push_back(lPusherCreator.getPusher()); } /** * @overload Operation::write(ParamDataIndexInfo &pParamDataIndexInfo) */ void write(ParamDataIndexInfo &pParamDataIndexInfo) { unsigned int index = pParamDataIndexInfo._startIndex; for (; index< pParamDataIndexInfo._startIndex + pParamDataIndexInfo._nbDataToProcess; index++) { for(auto operation : _operationList) { operation->write(index); } } } protected: /** * @brief It is the channel of the data shifted. */ TParamOutput *_paramOutput; }; } /* namespace Merge */ } /* namespace AMDA */ #endif /* Scheduler_HH_ */