1
0
This repository has been archived on 2024-01-25. You can view files and clone it, but cannot push or open issues or pull requests.
Files
RealtimeOscilloscope/src/xf/port/default/timeoutmanager-default.cpp
2023-11-28 14:19:36 +01:00

227 lines
6.5 KiB
C++

#include <config/xf-config.h>
#if (USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION != 0)
#include <cassert>
#include "xf/interface/reactive.h"
#include "xf/interface/mutex.h"
#include "port-functions.h"
#include "timeoutmanager-default.h"
using interface::XFMutex;
interface::XFTimeoutManager * interface::XFTimeoutManager::getInstance()
{
return XFTimeoutManagerDefault::getInstance();
}
interface::XFTimeoutManager * XFTimeoutManagerDefault::getInstance()
{
static XFTimeoutManagerDefault timeoutManager;
return &timeoutManager;
}
XFTimeoutManagerDefault::XFTimeoutManagerDefault() :
pMutex_(nullptr)
{
pMutex_ = XFMutex::create();
assert(pMutex_);
}
XFTimeoutManagerDefault::~XFTimeoutManagerDefault()
{
}
void XFTimeoutManagerDefault::start()
{
// Check tickInterval. Set default value if not set
if (tickInterval_ == 0)
{
tickInterval_ = 10;
}
XF_startTimeoutManagerTimer(uint32_t(tickInterval_));
}
void XFTimeoutManagerDefault::scheduleTimeout(int32_t timeoutId, int32_t interval, interface::XFReactive * pReactive)
{
XFTimeout * pTimeout = new XFTimeout(timeoutId, interval, pReactive);
if (pTimeout)
{
addTimeout(pTimeout);
}
}
void XFTimeoutManagerDefault::unscheduleTimeout(int32_t timeoutId, interface::XFReactive * pReactive)
{
const XFTimeout timeout(timeoutId, 0, pReactive);
XFTimeout * pTimeout;
pMutex_->lock();
{
for (TimeoutList::iterator i = timeouts_.begin();
i != timeouts_.end(); /*Do not increment here!*/)
{
pTimeout = *i;
// Check if behavior and timeout id are equal
if (*pTimeout == timeout)
{
TimeoutList::iterator next = i;
// Check if remaining ticks can be given further
if (++next != timeouts_.end())
{
// Add (remaining) ticks to next timeout in list
(*next)->addToRelTicks(pTimeout->getRelTicks());
}
i = timeouts_.erase(i);
// Iterator now points to the next element
delete pTimeout;
}
else
{
i++;
}
}
}
pMutex_->unlock();
}
void XFTimeoutManagerDefault::tick()
{
assert(tickInterval_); // Did you call start()?!
int32_t intervalToSubtract = tickInterval_;
while (!timeouts_.empty())
{
pMutex_->lock();
{
XFTimeout * pFirstTimeout = timeouts_.front();
// Subtract time elapsed
pFirstTimeout->substractFromRelTicks(intervalToSubtract);
// From now on set it to zero.
intervalToSubtract = 0;
// Check timeout timed out
if (pFirstTimeout->getRelTicks() <= 0)
{
// Check remaining ticks can be given further
if (timeouts_.size() > 1)
{
TimeoutList::iterator i = timeouts_.begin();
// Add ticks overrun to next timeout
i++;
(*i)->substractFromRelTicks(abs(pFirstTimeout->getRelTicks()));
}
// Inject the timeout back to the behavioral class
returnTimeout(pFirstTimeout);
// Remove timeout
timeouts_.pop_front();
// Check if timeouts with same timeout value are present
for (TimeoutList::iterator it = timeouts_.begin(); it != timeouts_.end(); /*Do not increment here!*/)
{
if ((*it)->getRelTicks() == 0)
{
returnTimeout(*it); // Return them true
it = timeouts_.erase(it); // Remove timeout and adjust iterator to next element
}
else
{
break;
}
}
}
else
{
pMutex_->unlock();
// Done. Exit while loop
break;
}
}
pMutex_->unlock();
}
}
void XFTimeoutManagerDefault::addTimeout(XFTimeout * pNewTimeout)
{
if (!timeouts_.empty())
{
pMutex_->lock();
{
// Insert timeout before timeout(s) triggering later
TimeoutList::iterator i = timeouts_.begin();
unsigned int index = 0;
// Find the right place to insert new timeout
while (i != timeouts_.end() &&
(*i)->getRelTicks() < pNewTimeout->getRelTicks())
{ // -> by: test4, test5
pNewTimeout->substractFromRelTicks((*i)->getRelTicks());
i++; index++;
}
if (i != timeouts_.end())
{
if ((*i)->getRelTicks() != pNewTimeout->getRelTicks())
{ // -> by: test1, test4, test5
// Timeout are going to timeout at different times
// Insert new timeout before
timeouts_.insert(i, pNewTimeout);
// Remove time from following timeout
(*i)->substractFromRelTicks(pNewTimeout->getRelTicks());
}
else
{ // -> by: test1, test5
const int32_t relTicks = (*i)->getRelTicks();
// Timeouts timeout at the same time. Put
// the new one behind the actual.
i++;
// Check if even more timeouts with the same timeout
while(i != timeouts_.end() && (*i)->getRelTicks() == 0)
{ // -> by: test5
i++;
}
// Insert new timeout behind actual
timeouts_.insert(i, pNewTimeout);
// Remove time from actual timeout
pNewTimeout->substractFromRelTicks(relTicks);
}
}
else
{ // -> by: test4, test5
// Add timeout at the end of the list
timeouts_.insert(timeouts_.end(), pNewTimeout);
}
}
pMutex_->unlock();
}
else
{ // -> by: test1, test2, test3, test4, test5
timeouts_.push_front(pNewTimeout);
}
}
void XFTimeoutManagerDefault::returnTimeout(XFTimeout * pTimeout)
{
pTimeout->getBehavior()->pushEvent(pTimeout);
}
#endif // USE_XF_TIMEOUTMANAGER_DEFAULT_IMPLEMENTATION