mirror of https://github.com/PurpleI2P/i2pd.git
I2P: End-to-End encrypted and anonymous Internet
https://i2pd.website/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.1 KiB
140 lines
4.1 KiB
#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; |
|
}
|
|
|