#include "PipeLine.h" #include "logger.h" PipeMaterial::PipeMaterial() : type(PMT__FIRST), buffer(nullptr), buffSize(0), former(nullptr), deleter(nullptr), args(nullptr) { } void PipeMaterial::exec_deleter() { if (deleter != nullptr) { deleter(this); deleter = nullptr; } } PipeLine::elem_create_func_map_t PipeLine::global_elem_create_func_map; PipeLine::PipeLine() : params_map(), elem_create_func_map(), elems() { } PipeLine::~PipeLine() { // pipe stop for(elem_vec_t::iterator iter = elems.begin(); iter != elems.end(); ++iter) { PipeLineElem* elem = *iter; if (elem != nullptr && elem->manager == this) { elem->finit(); delete *iter; } } elems.clear(); } bool PipeLine::register_elem_creator(const std::string& type, elem_create_func_t func) { if (type.empty() || func == nullptr) return false; elem_create_func_map_t::iterator iter = elem_create_func_map.find(type); if (iter != elem_create_func_map.end()) return false; elem_create_func_map.insert(std::make_pair(type, func)); return true; } //static bool PipeLine::register_global_elem_creator(const std::string& type, elem_create_func_t func) { if (type.empty() || func == nullptr) return false; elem_create_func_map_t::iterator iter = global_elem_create_func_map.find(type); if (iter != global_elem_create_func_map.end()) return false; global_elem_create_func_map.insert(std::make_pair(type, func)); return true; } void PipeLine::push_elem(PipeLineElem* elem) { if(elem != nullptr) { elem->manager = this; elems.push_back(elem); } } void PipeLine::push_front_elem(PipeLineElem* elem) { if(elem != nullptr) { elem->manager = this; elems.insert(elems.begin(), elem); } } bool PipeLine::remove_elem(PipeLineElem* elem) { if(elem != nullptr) { for(elem_vec_t::iterator iter = elems.begin(); iter != elems.end(); ++iter) { if (*iter == elem) { iter = elems.erase(iter); return true; } } } return false; } bool PipeLine::check_pipe_complete(PipeLineElem* lastRetElem) const { return lastRetElem == *elems.rbegin(); } PipeLineElem* PipeLine::push_elem(const std::string& type) { elem_create_func_map_t::iterator iter = elem_create_func_map.find(type); if (iter == elem_create_func_map.end()) { iter = global_elem_create_func_map.find(type); if (iter == global_elem_create_func_map.end()) return nullptr; } elem_create_func_t func = iter->second; if (func == nullptr) return nullptr; PipeLineElem* elem = func(); if (elem == nullptr) return nullptr; elem->manager = this; push_elem(elem); return elem; } class PipeDebugger { private: PipeLine* pipeLine; public: PipeLineElem* retElem; PipeMaterial* pm; PipeDebugger(PipeLine* _pipeLine) : pipeLine(_pipeLine), retElem(nullptr), pm(nullptr) { //LOG_DEBUG << "pipe line begin" << std::endl; } ~PipeDebugger() { //bool retOK = (*(pipeLine->elems).rbegin() == retElem); //if (retOK) // LOG_DEBUG << "pipe line end, ret OK" << std::endl; //else // LOG_WARN << "pipe line end, ret ERROR" << std::endl; } }; PipeLineElem* PipeLine::pipe(PipeMaterial* pm /*= nullptr*/) { PipeDebugger debugger(this); PipeLineElem* elem_begin = *elems.begin(); PipeLineElem* elem_last = *elems.rbegin(); if (elems.empty() || elem_begin == nullptr || elem_last == nullptr) return nullptr; uint8_t pmPlacement[sizeof(PipeMaterial)]; if (pm == nullptr) pm = new (pmPlacement) PipeMaterial; debugger.pm = pm; if (elems.size() == 1) { elem_begin->gain(*pm); pm->exec_deleter(); return debugger.retElem = elem_begin; } else if (elems.size() == 2) { if (elem_begin->gain(*pm)) { elem_last->pay(*pm); pm->exec_deleter(); } else return debugger.retElem = elem_begin; return debugger.retElem = elem_last; } else { if (!elem_begin->gain(*pm)) return debugger.retElem = elem_begin; bool lastRet = true; elem_vec_t::iterator iter = elems.begin(); ++iter; elem_begin = *iter; while (elem_begin != elem_last) { if (lastRet && (lastRet = elem_begin->pay(*pm)) ) { pm->exec_deleter(); lastRet = elem_begin->gain(*pm); } else return debugger.retElem = elem_begin; ++iter; elem_begin = *iter; } if (lastRet) { elem_last->pay(*pm); pm->exec_deleter(); } return debugger.retElem = elem_last; } return nullptr; } void PipeLine::set_param(const std::string& name, const std::string& value) { if (name.empty()) return; params_map_t::iterator iter = params_map.find(name); if (iter == params_map.end()) params_map.insert(std::make_pair(name, value)); else iter->second = value; } std::string PipeLine::get_param(const std::string& name) const { params_map_t::const_iterator iter = params_map.find(name); if (iter == params_map.end()) return ""; else return iter->second; }