#define MS_CLASS "RTC::SeqManager"
#include "RTC/SeqManager.hpp"
#include "Logger.hpp"
#include "Utils.hpp"
#include <iterator>
namespace RTC
{
template<typename T, uint8_t N>
bool SeqManager<T, N>::SeqLowerThan::operator()(T lhs, T rhs) const
{
return Utils::Number<T, N>::IsLowerThan(lhs, rhs);
}
template<typename T, uint8_t N>
bool SeqManager<T, N>::SeqHigherThan::operator()(T lhs, T rhs) const
{
return Utils::Number<T, N>::IsHigherThan(lhs, rhs);
}
template<typename T, uint8_t N>
bool SeqManager<T, N>::IsSeqHigherThan(T lhs, T rhs)
{
return Utils::Number<T, N>::IsHigherThan(lhs, rhs);
}
template<typename T, uint8_t N>
bool SeqManager<T, N>::IsSeqLowerThan(T lhs, T rhs)
{
return Utils::Number<T, N>::IsLowerThan(lhs, rhs);
}
template<typename T, uint8_t N>
SeqManager<T, N>::SeqManager(T initialOutput) : initialOutput(initialOutput)
{
MS_TRACE();
}
template<typename T, uint8_t N>
void SeqManager<T, N>::Sync(T input)
{
MS_TRACE();
this->base = (this->maxOutput - input) & SeqManager::MaxValue;
this->maxInput = input;
this->dropped.clear();
}
template<typename T, uint8_t N>
void SeqManager<T, N>::Drop(T input)
{
MS_TRACE();
if (SeqManager<T, N>::IsSeqHigherThan(input, this->maxInput))
{
this->maxInput = input;
this->dropped.insert(this->dropped.end(), input);
ClearDropped();
}
}
template<typename T, uint8_t N>
bool SeqManager<T, N>::Input(T input, T& output)
{
MS_TRACE();
auto base = this->base;
if (this->dropped.empty())
{
goto done;
}
else
{
if (this->started && SeqManager<T, N>::IsSeqHigherThan(input, this->maxInput))
{
this->maxInput = input;
}
ClearDropped();
base = this->base;
}
if (this->dropped.empty())
{
goto done;
}
else if (this->dropped.find(input) != this->dropped.end())
{
MS_DEBUG_DEV("trying to send a dropped input");
return false;
}
else
{
auto droppedCount = this->dropped.size();
auto it = this->dropped.lower_bound(input);
droppedCount -= std::distance(it, this->dropped.end());
base = (this->base - droppedCount) & SeqManager::MaxValue;
}
done:
output = (input + base) & SeqManager::MaxValue;
if (!this->started)
{
this->started = true;
this->maxInput = input;
this->maxOutput = output;
}
else
{
if (SeqManager<T, N>::IsSeqHigherThan(input, this->maxInput))
{
this->maxInput = input;
}
if (SeqManager<T, N>::IsSeqHigherThan(output, this->maxOutput))
{
this->maxOutput = output;
}
}
output = (output + this->initialOutput) & SeqManager::MaxValue;
return true;
}
template<typename T, uint8_t N>
T SeqManager<T, N>::GetMaxInput() const
{
return this->maxInput;
}
template<typename T, uint8_t N>
T SeqManager<T, N>::GetMaxOutput() const
{
return this->maxOutput;
}
template<typename T, uint8_t N>
void SeqManager<T, N>::ClearDropped()
{
MS_TRACE();
if (this->dropped.empty())
{
return;
}
const size_t previousDroppedSize = this->dropped.size();
for (auto it = this->dropped.begin(); it != this->dropped.end();)
{
auto value = *it;
if (SeqManager<T, N>::IsSeqHigherThan(value, this->maxInput))
{
it = this->dropped.erase(it);
}
else
{
break;
}
}
this->base = (this->base - (previousDroppedSize - this->dropped.size())) & SeqManager::MaxValue;
}
template class SeqManager<uint8_t>; template class SeqManager<uint8_t, 3>; template class SeqManager<uint16_t>; template class SeqManager<uint16_t, 15>; }