mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2026-06-05 15:35:01 -04:00
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:
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user