mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2024-11-04 06:00:37 +00:00
141 lines
4.1 KiB
C++
141 lines
4.1 KiB
C++
#include "DelayedSaveManagerImpl.h"
|
|
|
|
DelayedSaveManagerImpl::DelayedSaveManagerImpl() :
|
|
saver(nullptr),
|
|
lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL),
|
|
lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP),
|
|
exiting(false),
|
|
thread(new DelayedSaveThread(this))
|
|
{
|
|
}
|
|
|
|
void DelayedSaveManagerImpl::setSaver(Saver* saver) {
|
|
this->saver = saver;
|
|
}
|
|
|
|
void DelayedSaveManagerImpl::start() {
|
|
thread->start();
|
|
}
|
|
|
|
bool DelayedSaveManagerImpl::isSaverValid() {
|
|
return saver != nullptr;
|
|
}
|
|
|
|
void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus_) {
|
|
if(lastDataSerialSeen==dataSerial)return;
|
|
this->focusOnTunnel = focusOnTunnel;
|
|
tunnelNameToFocus = tunnelNameToFocus_;
|
|
lastDataSerialSeen=dataSerial;
|
|
assert(isSaverValid());
|
|
TIMESTAMP_TYPE now = getTime();
|
|
TIMESTAMP_TYPE wakeTime = lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS;
|
|
if(now < wakeTime) {
|
|
//defer save until lastSaveStartedTimestamp + DelayedSaveThread::WAIT_TIME_MILLIS
|
|
thread->deferSaveUntil(wakeTime);
|
|
return;
|
|
}
|
|
lastSaveStartedTimestamp = now;
|
|
thread->startSavingNow();
|
|
}
|
|
|
|
bool DelayedSaveManagerImpl::appExiting() {
|
|
exiting=true;
|
|
thread->wakeThreadAndJoinThread();
|
|
assert(isSaverValid());
|
|
saver->save(false, "");
|
|
return true;
|
|
}
|
|
|
|
DelayedSaveThread::DelayedSaveThread(DelayedSaveManagerImpl* delayedSaveManagerImpl_):
|
|
delayedSaveManagerImpl(delayedSaveManagerImpl_),
|
|
mutex(new QMutex()),
|
|
waitCondition(new QWaitCondition()),
|
|
saveNow(false),
|
|
defer(false)
|
|
{
|
|
mutex->lock();
|
|
}
|
|
|
|
DelayedSaveThread::~DelayedSaveThread(){
|
|
mutex->unlock();
|
|
delete mutex;
|
|
delete waitCondition;
|
|
}
|
|
|
|
void DelayedSaveThread::run() {
|
|
forever {
|
|
if(delayedSaveManagerImpl->isExiting())return;
|
|
waitCondition->wait(mutex, WAIT_TIME_MILLIS);
|
|
if(delayedSaveManagerImpl->isExiting())return;
|
|
Saver* saver = delayedSaveManagerImpl->getSaver();
|
|
assert(saver!=nullptr);
|
|
if(saveNow) {
|
|
saveNow = false;
|
|
const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel();
|
|
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
|
saver->save(focusOnTunnel, tunnelNameToFocus);
|
|
continue;
|
|
}
|
|
if(defer) {
|
|
defer=false;
|
|
#define max(a,b) (((a)>(b))?(a):(b))
|
|
forever {
|
|
TIMESTAMP_TYPE now = DelayedSaveManagerImpl::getTime();
|
|
TIMESTAMP_TYPE millisToWait = max(wakeTime-now, 0);
|
|
if(millisToWait>0) {
|
|
waitCondition->wait(mutex, millisToWait);
|
|
if(delayedSaveManagerImpl->isExiting())return;
|
|
continue;
|
|
}
|
|
const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel();
|
|
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
|
saver->save(focusOnTunnel, tunnelNameToFocus);
|
|
break; //break inner loop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void DelayedSaveThread::wakeThreadAndJoinThread() {
|
|
waitCondition->wakeAll();
|
|
quit();
|
|
wait();//join //"similar to the POSIX pthread_join()"
|
|
}
|
|
|
|
DelayedSaveManagerImpl::TIMESTAMP_TYPE DelayedSaveManagerImpl::getTime() {
|
|
return QDateTime::currentMSecsSinceEpoch();
|
|
}
|
|
|
|
void DelayedSaveThread::deferSaveUntil(TIMESTAMP_TYPE wakeTime_) {
|
|
wakeTime = wakeTime_;
|
|
defer = true;
|
|
waitCondition->wakeAll();
|
|
}
|
|
|
|
void DelayedSaveThread::startSavingNow() {
|
|
//mutex->lock();
|
|
saveNow=true;
|
|
waitCondition->wakeAll();
|
|
//mutex->unlock();
|
|
}
|
|
|
|
DelayedSaveManagerImpl::~DelayedSaveManagerImpl() {
|
|
thread->wakeThreadAndJoinThread();
|
|
delete thread;
|
|
}
|
|
|
|
bool DelayedSaveManagerImpl::isExiting() {
|
|
return exiting;
|
|
}
|
|
Saver* DelayedSaveManagerImpl::getSaver() {
|
|
return saver;
|
|
}
|
|
|
|
bool DelayedSaveManagerImpl::needsFocusOnTunnel() {
|
|
return focusOnTunnel;
|
|
}
|
|
|
|
std::string& DelayedSaveManagerImpl::getTunnelNameToFocus() {
|
|
return tunnelNameToFocus;
|
|
}
|