#include "PipeLine.h"
|
#include "MaterialBuffer.h"
|
#include "logger.h"
|
|
PipeMaterial::PipeMaterial() :
|
type(PMT__FIRST), buffer(nullptr), buffSize(0),
|
former(nullptr), deleter(nullptr), args(nullptr)
|
{
|
}
|
|
void PipeMaterial::exec_deleter(bool lastRet)
|
{
|
if (deleter != nullptr)
|
{
|
deleter(this, lastRet);
|
deleter = nullptr;
|
}
|
}
|
|
int PipeMaterial::breake(PipeMaterialBufferType selectPmType, int _selectMbfType,
|
pm_breaker_func breaker, void* args /*= nullptr*/) const
|
{
|
int called = 0;
|
const MB_Frame::MBFType selectMbfType = (MB_Frame::MBFType)_selectMbfType;
|
|
switch(type)
|
{
|
case PMT_NONE:
|
if (selectPmType == PMT_NONE)
|
{
|
called++;
|
breaker(this, args);
|
}
|
break;
|
case PMT_BYTES:
|
if (selectPmType == PMT_BYTES)
|
{
|
called++;
|
breaker(this, args);
|
}
|
break;
|
case PMT_PTR:
|
if (selectPmType == PMT_PTR)
|
{
|
called++;
|
breaker(this, args);
|
}
|
break;
|
case PMT_FRAME:
|
if (selectPmType == PMT_FRAME || selectPmType == PipeMaterial::PMT__FIRST || selectPmType == PipeMaterial::PMT__LAST)
|
{
|
MB_Frame* mbf = (MB_Frame*)buffer;
|
if (selectMbfType == mbf->type || selectMbfType == MB_Frame::MBFT__FIRST || selectMbfType == MB_Frame::MBFT__LAST)
|
{
|
called++;
|
breaker(this, args);
|
}
|
}
|
break;
|
case PMT_PM_LIST:
|
{
|
// break pm list into single pm(s)
|
|
PipeMaterial* pm = (PipeMaterial*)buffer;
|
for (size_t i = 0; i < buffSize; i++, pm++)
|
{
|
if (selectPmType == pm->type || selectPmType == PipeMaterial::PMT__FIRST || selectPmType == PipeMaterial::PMT__LAST)
|
{
|
if (pm->type == PipeMaterial::PMT_FRAME)
|
{
|
MB_Frame *mbf = (MB_Frame *) pm->buffer;
|
if (selectMbfType == mbf->type || selectMbfType == MB_Frame::MBFT__FIRST || selectMbfType == MB_Frame::MBFT__LAST)
|
{
|
called++;
|
if (!breaker(pm, args))
|
break;
|
}
|
}
|
else
|
{
|
called++;
|
if (!breaker(pm, args))
|
break;
|
}
|
}
|
}
|
}
|
break;
|
case PMT_FRAME_LIST:
|
{
|
// break mbf list into single pm(s)
|
|
if (selectPmType == PMT_FRAME_LIST || selectPmType == PMT_FRAME ||
|
selectPmType == PipeMaterial::PMT__FIRST || selectPmType == PipeMaterial::PMT__LAST)
|
{
|
MB_Frame* mbf = (MB_Frame*)buffer;
|
for (size_t i = 0; i < buffSize; i++, mbf++)
|
{
|
if (selectMbfType == mbf->type || selectMbfType == MB_Frame::MBFT__FIRST || selectMbfType == MB_Frame::MBFT__LAST)
|
{
|
PipeMaterial tmpPm;
|
tmpPm.type = PMT_FRAME;
|
tmpPm.buffer = mbf;
|
tmpPm.buffSize = 0;
|
tmpPm.former = former;
|
tmpPm.deleter = nullptr;
|
tmpPm.args = args;
|
|
called++;
|
if (!breaker(&tmpPm, args))
|
break;
|
}
|
}
|
}
|
}
|
break;
|
default:
|
break;
|
}
|
|
return called;
|
}
|
|
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);
|
}
|
}
|
|
PipeLineElem* PipeLine::at(int idx)
|
{
|
return elems[idx];
|
}
|
|
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;
|
}
|
|
void PipeLine::finit(elem_destory_func_t elem_destory_func)
|
{
|
while (!elems.empty())
|
{
|
PipeLineElem* elem = elems.back();
|
|
if (elem->manager == this)
|
{
|
elem->finit();
|
if (elem_destory_func != nullptr)
|
elem_destory_func(elem);
|
}
|
|
elems.pop_back();
|
}
|
|
elem_create_func_map.clear();
|
params_map.clear();
|
}
|
|
bool PipeLine::check_pipe_complete(PipeLineElem* lastRetElem) const
|
{
|
if (elems.empty())
|
return lastRetElem == nullptr;
|
else
|
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;
|
}
|
|
PipeLineElem* PipeLine::pipe(PipeMaterial* pm /*= nullptr*/)
|
{
|
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;
|
|
bool lastRet = true;
|
|
if (elems.size() == 1)
|
{
|
lastRet = elem_begin->gain(*pm);
|
pm->exec_deleter(lastRet);
|
return elem_begin;
|
}
|
else if (elems.size() == 2)
|
{
|
if (elem_begin->gain(*pm))
|
{
|
lastRet = elem_last->pay(*pm);
|
pm->exec_deleter(lastRet);
|
}
|
else
|
return elem_begin;
|
return elem_last;
|
}
|
else
|
{
|
if (!elem_begin->gain(*pm))
|
return elem_begin;
|
|
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);
|
lastRet = elem_begin->gain(*pm);
|
}
|
else
|
return elem_begin;
|
|
++iter;
|
elem_begin = *iter;
|
}
|
|
if (lastRet)
|
elem_last->pay(*pm);
|
pm->exec_deleter(lastRet);
|
return 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;
|
}
|
|
#ifdef ENABLE_PIPELINE_ELEM_TIMING_DEBUGGER
|
#include <typeinfo>
|
#include <sys/time.h>
|
PipeLineElemTimingDebugger::PipeLineElemTimingDebugger(const PipeLineElem* _elem) :
|
elem(_elem), beginTime(0)
|
{
|
struct timeval _beginTime;
|
gettimeofday(&_beginTime, NULL);
|
beginTime = 1000000 * _beginTime.tv_sec + _beginTime.tv_usec;
|
}
|
|
PipeLineElemTimingDebugger::~PipeLineElemTimingDebugger()
|
{
|
struct timeval _endTime;
|
gettimeofday(&_endTime, NULL);
|
const uint64_t endTime = 1000000 * _endTime.tv_sec + _endTime.tv_usec;
|
|
LOGP(WARN, "elem=%s@%llu, dura=%llu(us)", typeid(elem).name(), uint64_t(elem), uint64_t(endTime - beginTime));
|
}
|
#else
|
PipeLineElemTimingDebugger::PipeLineElemTimingDebugger(const PipeLineElem* _elem) { }
|
PipeLineElemTimingDebugger::~PipeLineElemTimingDebugger() { }
|
#endif
|