Make ReBuffer refcount management automatic, using std::shared_ptr:

- No longer need to call setRefCount() / decRefCount()
- Restore old ThreadBlockingQueue using std::deque, for std::shared_ptr correct behaviour.
This commit is contained in:
vsonnier
2017-05-24 12:24:36 +02:00
parent 8776908340
commit 4b323e9863
32 changed files with 289 additions and 409 deletions
+4 -3
View File
@@ -28,7 +28,7 @@ void FFTDataDistributor::process() {
if (!isAnyOutputEmpty()) {
return;
}
DemodulatorThreadIQData *inp;
DemodulatorThreadIQDataPtr inp;
input->pop(inp);
if (inp) {
@@ -73,7 +73,7 @@ void FFTDataDistributor::process() {
memcpy(&inputBuffer.data[bufferOffset+bufferedItems],&inp->data[0], nbSamplesToAdd *sizeof(liquid_float_complex));
bufferedItems += nbSamplesToAdd;
//
inp->decRefCount();
} else {
//empty inp, wait for another.
continue;
@@ -105,7 +105,8 @@ void FFTDataDistributor::process() {
if (lineRateAccum >= 1.0) {
//each i represents a FFT computation
DemodulatorThreadIQData *outp = outputBuffers.getBuffer();
DemodulatorThreadIQDataPtr outp = outputBuffers.getBuffer();
outp->frequency = inputBuffer.frequency;
outp->sampleRate = inputBuffer.sampleRate;
outp->data.assign(inputBuffer.data.begin()+bufferOffset+i,
+6 -7
View File
@@ -47,7 +47,7 @@ void ScopeVisualProcessor::process() {
if (!isOutputEmpty()) {
return;
}
AudioThreadInput *audioInputData;
AudioThreadInputPtr audioInputData;
if (input->try_pop(audioInputData)) {
@@ -56,11 +56,12 @@ void ScopeVisualProcessor::process() {
}
size_t i, iMax = audioInputData->data.size();
if (!iMax) {
delete audioInputData; //->decRefCount();
//discard audioInputData.
audioInputData = nullptr;
return;
}
ScopeRenderData *renderData = NULL;
ScopeRenderDataPtr renderData = nullptr;
if (scopeEnabled) {
iMax = audioInputData->data.size();
@@ -150,7 +151,7 @@ void ScopeVisualProcessor::process() {
renderData->inputRate = audioInputData->inputRate;
renderData->sampleRate = audioInputData->sampleRate;
delete audioInputData; //->decRefCount();
audioInputData = nullptr; //->decRefCount();
double fft_ceil = 0, fft_floor = 1;
@@ -212,8 +213,6 @@ void ScopeVisualProcessor::process() {
renderData->spectrum = true;
distribute(renderData);
} else {
delete audioInputData; //->decRefCount();
}
}
} //end if try_pop()
}
+9 -2
View File
@@ -6,8 +6,9 @@
#include "VisualProcessor.h"
#include "AudioThread.h"
#include "ScopePanel.h"
#include <memory>
class ScopeRenderData: public ReferenceCounter {
class ScopeRenderData {
public:
std::vector<float> waveform_points;
ScopePanel::ScopeMode mode = ScopePanel::SCOPE_MODE_Y;
@@ -17,9 +18,15 @@ public:
bool spectrum;
int fft_size;
double fft_floor, fft_ceil;
virtual ~ScopeRenderData() {
}
};
typedef ThreadBlockingQueue<ScopeRenderData *> ScopeRenderDataQueue;
typedef std::shared_ptr<ScopeRenderData> ScopeRenderDataPtr;
typedef ThreadBlockingQueue<ScopeRenderDataPtr> ScopeRenderDataQueue;
class ScopeVisualProcessor : public VisualProcessor<AudioThreadInput, ScopeRenderData> {
public:
+3 -13
View File
@@ -192,7 +192,7 @@ void SpectrumVisualProcessor::process() {
fftSizeChanged.store(false);
}
DemodulatorThreadIQData *iqData;
DemodulatorThreadIQDataPtr iqData;
input->pop(iqData);
@@ -200,14 +200,8 @@ void SpectrumVisualProcessor::process() {
return;
}
//Start by locking concurrent access to iqData
std::lock_guard < std::recursive_mutex > lock(iqData->getMonitor());
//then get the busy_lock
std::lock_guard < std::mutex > busy_lock(busy_run);
bool doPeak = peakHold.load() && (peakReset.load() == 0);
@@ -246,7 +240,6 @@ void SpectrumVisualProcessor::process() {
if (is_view.load()) {
if (!iqData->sampleRate) {
iqData->decRefCount();
return;
}
@@ -387,7 +380,7 @@ void SpectrumVisualProcessor::process() {
}
if (execute) {
SpectrumVisualData *output = outputBuffers.getBuffer();
SpectrumVisualDataPtr output = outputBuffers.getBuffer();
if (output->spectrum_points.size() != fftSize * 2) {
output->spectrum_points.resize(fftSize * 2);
@@ -597,10 +590,7 @@ void SpectrumVisualProcessor::process() {
distribute(output);
}
}
iqData->decRefCount();
}
lastView = is_view.load();
}
+6 -2
View File
@@ -6,20 +6,24 @@
#include "VisualProcessor.h"
#include "DemodDefs.h"
#include <cmath>
#include <memory>
#define SPECTRUM_VZM 2
#define PEAK_RESET_COUNT 30
class SpectrumVisualData : public ReferenceCounter {
class SpectrumVisualData {
public:
std::vector<float> spectrum_points;
std::vector<float> spectrum_hold_points;
double fft_ceiling, fft_floor;
long long centerFreq;
int bandwidth;
virtual ~SpectrumVisualData() {};
};
typedef ThreadBlockingQueue<SpectrumVisualData *> SpectrumVisualDataQueue;
typedef std::shared_ptr<SpectrumVisualData> SpectrumVisualDataPtr;
typedef ThreadBlockingQueue<SpectrumVisualDataPtr> SpectrumVisualDataQueue;
class SpectrumVisualProcessor : public VisualProcessor<DemodulatorThreadIQData, SpectrumVisualData> {
public:
+23 -23
View File
@@ -9,11 +9,16 @@
#include <algorithm>
#include <vector>
template<typename InputDataType = ReferenceCounter, typename OutputDataType = ReferenceCounter>
template<typename InputDataType, typename OutputDataType>
class VisualProcessor {
//
typedef ThreadBlockingQueue<InputDataType*> VisualInputQueueType;
typedef ThreadBlockingQueue<OutputDataType*> VisualOutputQueueType;
typedef std::shared_ptr<InputDataType> InputDataTypePtr;
typedef std::shared_ptr<OutputDataType> OutputDataTypePtr;
typedef ThreadBlockingQueue<InputDataTypePtr> VisualInputQueueType;
typedef ThreadBlockingQueue<OutputDataTypePtr> VisualOutputQueueType;
typedef typename std::vector< VisualOutputQueueType *>::iterator outputs_i;
public:
virtual ~VisualProcessor() {
@@ -96,22 +101,19 @@ protected:
//available outputs, previously set by attachOutput().
//* \param[in] timeout The number of microseconds to wait to push an item in each one of the outputs, 0(default) means indefinite wait.
//* \param[in] errorMessage an error message written on std::cout in case pf push timeout.
void distribute(OutputDataType *item, std::uint64_t timeout = BLOCKING_INFINITE_TIMEOUT, const char* errorMessage = "") {
void distribute(OutputDataTypePtr item, std::uint64_t timeout = BLOCKING_INFINITE_TIMEOUT, const char* errorMessage = "") {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
//We will try to distribute 'output' among all 'outputs',
//so 'output' will a-priori be shared among all 'outputs' so set its ref count to this
//amount.
item->setRefCount((int)outputs.size());
//so 'output' will a-priori be shared among all 'outputs'.
for (outputs_i it = outputs.begin(); it != outputs.end(); it++) {
//if 'output' failed to be given to an outputs_i, dec its ref count accordingly.
//blocking push, with a timeout
//'output' can fail to be given to an outputs_i,
//using a blocking push, with a timeout
if (!(*it)->push(item, timeout, errorMessage)) {
item->decRefCount();
//TODO : trace ?
}
}
// Now 'item' refcount matches the times 'item' has been successfully distributed,
//i.e shared among the outputs.
}
//the incoming data queue
@@ -127,7 +129,7 @@ protected:
//Specialization much like VisualDataReDistributor, except
//the input (pointer) is directly re-dispatched
//to outputs, so that all output indeed SHARE the same instance.
template<typename OutputDataType = ReferenceCounter>
template<typename OutputDataType>
class VisualDataDistributor : public VisualProcessor<OutputDataType, OutputDataType> {
protected:
virtual void process() {
@@ -136,18 +138,14 @@ protected:
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
if (inp) {
inp->decRefCount();
//nothing
}
return;
}
if (inp) {
int previousRefCount = inp->getRefCount();
VisualProcessor<OutputDataType, OutputDataType>::distribute(inp);
//inp is now shared through the distribute(), which overwrite the previous ref count,
//so increment it properly.
int distributeRefCount = inp->getRefCount();
inp->setRefCount(previousRefCount + distributeRefCount);
//inp is now shared through the distribute() call.
}
}
}
@@ -155,7 +153,7 @@ protected:
//specialization class which process() take an input item and re-dispatch
//A COPY to every outputs, without further processing. This is a 1-to-n dispatcher.
template<typename OutputDataType = ReferenceCounter>
template<typename OutputDataType>
class VisualDataReDistributor : public VisualProcessor<OutputDataType, OutputDataType> {
protected:
virtual void process() {
@@ -164,15 +162,17 @@ protected:
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
if (inp) {
inp->decRefCount();
//nothing
}
return;
}
if (inp) {
OutputDataType *outp = buffers.getBuffer();
OutputDataTypePtr outp = buffers.getBuffer();
//'deep copy of the contents
(*outp) = (*inp);
inp->decRefCount();
VisualProcessor<OutputDataType, OutputDataType>::distribute(outp);
}
}