mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2024-11-29 23:28:39 -05:00
Even better thread and application termination:
- Now that timed-pop()/try_pop() prevent indefinite blocking it is best to flush() on thread stopping to unblock push() - Reworked a bit the CubicSDR::OnExit() sequence, see comments.
This commit is contained in:
parent
8f608bbf5c
commit
3604b7f1ff
@ -394,17 +394,18 @@ int CubicSDR::OnExit() {
|
||||
sdrThread->terminate();
|
||||
sdrThread->isTerminated(3000);
|
||||
|
||||
if (t_SDR) {
|
||||
t_SDR->join();
|
||||
delete t_SDR;
|
||||
t_SDR = nullptr;
|
||||
}
|
||||
|
||||
std::cout << "Terminating SDR post-processing thread.." << std::endl;
|
||||
sdrPostThread->terminate();
|
||||
|
||||
//Wait for termination for sdrPostThread second:: since it is doing
|
||||
//mostly blocking push() to the other threads, they must stay alive
|
||||
//so that sdrPostThread can complete a processing loop and die.
|
||||
sdrPostThread->isTerminated(3000);
|
||||
|
||||
std::cout << "Terminating All Demodulators.." << std::endl;
|
||||
demodMgr.terminateAll();
|
||||
//wait for effective death of all demodulators before continuing.
|
||||
demodMgr.garbageCollect(true);
|
||||
|
||||
std::cout << "Terminating Visual Processor threads.." << std::endl;
|
||||
spectrumVisualThread->terminate();
|
||||
@ -413,18 +414,28 @@ int CubicSDR::OnExit() {
|
||||
}
|
||||
|
||||
//Wait nicely
|
||||
sdrPostThread->isTerminated(1000);
|
||||
spectrumVisualThread->isTerminated(1000);
|
||||
if (demodVisualThread) {
|
||||
demodVisualThread->isTerminated(1000);
|
||||
}
|
||||
|
||||
//Then join the thread themselves
|
||||
//Then join the thread themselves:
|
||||
if (t_SDR) {
|
||||
t_SDR->join();
|
||||
}
|
||||
|
||||
t_PostSDR->join();
|
||||
if (t_DemodVisual) t_DemodVisual->join();
|
||||
|
||||
if (t_DemodVisual) {
|
||||
t_DemodVisual->join();
|
||||
}
|
||||
|
||||
t_SpectrumVisual->join();
|
||||
|
||||
//Now only we can delete
|
||||
//Now only we can delete:
|
||||
delete t_SDR;
|
||||
t_SDR = nullptr;
|
||||
|
||||
delete sdrThread;
|
||||
sdrThread = nullptr;
|
||||
|
||||
|
@ -278,12 +278,14 @@ DemodulatorInstance *DemodulatorMgr::getLastDemodulatorWith(const std::string& t
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DemodulatorMgr::garbageCollect() {
|
||||
void DemodulatorMgr::garbageCollect(boolean forcedGC) {
|
||||
|
||||
std::lock_guard < std::mutex > lock(deleted_demods_busy);
|
||||
|
||||
std::vector<DemodulatorInstance *>::iterator it = demods_deleted.begin();
|
||||
while (!demods_deleted.empty()) {
|
||||
|
||||
std::vector<DemodulatorInstance *>::iterator it = demods_deleted.begin();
|
||||
//make 1 pass over
|
||||
while (it != demods_deleted.end()) {
|
||||
|
||||
if ((*it)->isTerminated()) {
|
||||
@ -291,16 +293,21 @@ void DemodulatorMgr::garbageCollect() {
|
||||
DemodulatorInstance *deleted = (*it);
|
||||
|
||||
std::cout << "Garbage collected demodulator instance '" << deleted->getLabel() << "'... " << std::endl << std::flush;
|
||||
demods_deleted.erase(it);
|
||||
it = demods_deleted.erase(it);
|
||||
delete deleted;
|
||||
|
||||
//only garbage collect 1 demod at a time.
|
||||
if (!forcedGC) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
} //end while
|
||||
//stupid busy-wait loop
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
} //end while not empty
|
||||
}
|
||||
|
||||
void DemodulatorMgr::updateLastState() {
|
||||
|
@ -69,7 +69,11 @@ public:
|
||||
DemodulatorInstance *loadInstance(DataNode *node);
|
||||
|
||||
//to be called periodically to cleanup removed demodulators.
|
||||
void garbageCollect();
|
||||
//if forcedGC = true, the methods waits until
|
||||
//all deleted demodulators are effectively GCed.
|
||||
//else: (default) the method test for effective termination
|
||||
//and GC one demod per call.
|
||||
void garbageCollect(boolean forcedGC = false);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -282,7 +282,7 @@ void DemodulatorPreThread::run() {
|
||||
|
||||
|
||||
iqOutputQueue->flush();
|
||||
buffers.purge();
|
||||
iqInputQueue->flush();
|
||||
}
|
||||
|
||||
void DemodulatorPreThread::setDemodType(std::string demodType) {
|
||||
|
@ -343,8 +343,6 @@ void DemodulatorThread::run() {
|
||||
iqInputQueue->flush();
|
||||
audioOutputQueue->flush();
|
||||
|
||||
outputBuffers.purge();
|
||||
|
||||
// std::cout << "Demodulator thread done." << std::endl;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ void DemodulatorWorkerThread::run() {
|
||||
//Beware of the subtility here,
|
||||
//we are waiting for the first command to show up (blocking!)
|
||||
//then consuming the commands until done.
|
||||
while (!done) {
|
||||
while (!done && !stopping) {
|
||||
if (!commandQueue->pop(command, HEARTBEAT_CHECK_PERIOD_MICROS)) {
|
||||
continue;
|
||||
}
|
||||
@ -51,7 +51,7 @@ void DemodulatorWorkerThread::run() {
|
||||
break;
|
||||
}
|
||||
done = commandQueue->empty();
|
||||
}
|
||||
} //end while done.
|
||||
|
||||
if ((makeDemod || filterChanged) && !stopping) {
|
||||
DemodulatorWorkerThreadResult result(DemodulatorWorkerThreadResult::DEMOD_WORKER_THREAD_RESULT_FILTERS);
|
||||
|
@ -77,6 +77,9 @@ void FFTVisualDataThread::run() {
|
||||
}
|
||||
}
|
||||
|
||||
pipeIQDataIn->flush();
|
||||
pipeFFTDataOut->flush();
|
||||
|
||||
// std::cout << "FFT visual data thread done." << std::endl;
|
||||
}
|
||||
|
||||
|
@ -225,8 +225,9 @@ void SDRPostThread::run() {
|
||||
iqVisualQueue->flush();
|
||||
}
|
||||
|
||||
// buffers.purge();
|
||||
// visualDataBuffers.purge();
|
||||
iqDataInQueue->flush();
|
||||
iqDataOutQueue->flush();
|
||||
iqActiveDemodVisualQueue->flush();
|
||||
|
||||
// std::cout << "SDR post-processing thread done." << std::endl;
|
||||
}
|
||||
|
@ -377,8 +377,7 @@ void SDRThread::readLoop() {
|
||||
updateSettings();
|
||||
readStream(iqDataOutQueue);
|
||||
}
|
||||
|
||||
buffers.purge();
|
||||
iqDataOutQueue->flush();
|
||||
}
|
||||
|
||||
void SDRThread::updateGains() {
|
||||
|
Loading…
Reference in New Issue
Block a user