2017-01-02 21:07:43 -05:00
|
|
|
// Copyright (c) Charles J. Cliffe
|
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
|
|
|
|
2015-07-27 21:20:44 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "CubicSDRDefs.h"
|
|
|
|
#include "ThreadQueue.h"
|
2015-07-29 18:34:58 -04:00
|
|
|
#include "IOThread.h"
|
2015-07-31 18:21:30 -04:00
|
|
|
#include <algorithm>
|
2015-07-27 21:20:44 -04:00
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
template<class InputDataType = ReferenceCounter, class OutputDataType = ReferenceCounter>
|
2015-07-27 21:20:44 -04:00
|
|
|
class VisualProcessor {
|
|
|
|
public:
|
2015-07-31 21:03:17 -04:00
|
|
|
virtual ~VisualProcessor() {
|
|
|
|
|
|
|
|
}
|
2015-08-11 00:50:43 -04:00
|
|
|
|
|
|
|
bool isInputEmpty() {
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-08-11 00:50:43 -04:00
|
|
|
return input->empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isOutputEmpty() {
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-08-11 00:50:43 -04:00
|
|
|
for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) {
|
|
|
|
if ((*outputs_i)->full()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isAnyOutputEmpty() {
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-08-11 00:50:43 -04:00
|
|
|
for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) {
|
|
|
|
if (!(*outputs_i)->full()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2015-07-31 21:03:17 -04:00
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
void setInput(ThreadQueue<InputDataType *> *vis_in) {
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
2015-07-27 21:45:24 -04:00
|
|
|
input = vis_in;
|
2016-06-02 17:56:31 -04:00
|
|
|
|
2015-07-27 21:20:44 -04:00
|
|
|
}
|
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
void attachOutput(ThreadQueue<OutputDataType *> *vis_out) {
|
2015-07-27 21:20:44 -04:00
|
|
|
// attach an output queue
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
2015-07-27 21:45:24 -04:00
|
|
|
outputs.push_back(vis_out);
|
2016-06-02 17:56:31 -04:00
|
|
|
|
2015-07-27 21:20:44 -04:00
|
|
|
}
|
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
void removeOutput(ThreadQueue<OutputDataType *> *vis_out) {
|
2015-07-27 21:20:44 -04:00
|
|
|
// remove an output queue
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
typename std::vector<ThreadQueue<OutputDataType *> *>::iterator i = std::find(outputs.begin(), outputs.end(), vis_out);
|
2015-07-27 21:45:24 -04:00
|
|
|
if (i != outputs.end()) {
|
|
|
|
outputs.erase(i);
|
|
|
|
}
|
2016-06-02 17:56:31 -04:00
|
|
|
|
2015-07-27 21:20:44 -04:00
|
|
|
}
|
|
|
|
|
2015-07-27 21:45:24 -04:00
|
|
|
void run() {
|
2016-06-02 17:56:31 -04:00
|
|
|
|
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-07-27 22:05:35 -04:00
|
|
|
if (input && !input->empty()) {
|
|
|
|
process();
|
|
|
|
}
|
2016-06-02 17:56:31 -04:00
|
|
|
|
2015-07-27 21:20:44 -04:00
|
|
|
}
|
|
|
|
|
2015-07-27 22:05:35 -04:00
|
|
|
protected:
|
2015-07-27 21:20:44 -04:00
|
|
|
virtual void process() {
|
2015-07-27 21:45:24 -04:00
|
|
|
// process inputs to output
|
2015-07-27 21:20:44 -04:00
|
|
|
// distribute(output);
|
|
|
|
}
|
2015-07-27 22:05:35 -04:00
|
|
|
|
2015-07-31 21:03:17 -04:00
|
|
|
void distribute(OutputDataType *output) {
|
2015-07-27 21:20:44 -04:00
|
|
|
// distribute outputs
|
2016-06-02 17:56:31 -04:00
|
|
|
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
|
|
|
|
|
2015-07-27 21:45:24 -04:00
|
|
|
output->setRefCount(outputs.size());
|
2015-08-01 11:03:00 -04:00
|
|
|
for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) {
|
2016-07-06 15:23:59 -04:00
|
|
|
|
|
|
|
if (!(*outputs_i)->push(output)) {
|
2015-07-31 21:03:17 -04:00
|
|
|
output->decRefCount();
|
2016-07-06 15:23:59 -04:00
|
|
|
}
|
2015-07-27 21:45:24 -04:00
|
|
|
}
|
2015-07-27 21:20:44 -04:00
|
|
|
}
|
2015-07-31 21:03:17 -04:00
|
|
|
|
2015-07-31 21:28:14 -04:00
|
|
|
ThreadQueue<InputDataType *> *input;
|
|
|
|
std::vector<ThreadQueue<OutputDataType *> *> outputs;
|
|
|
|
typename std::vector<ThreadQueue<OutputDataType *> *>::iterator outputs_i;
|
2016-06-02 17:56:31 -04:00
|
|
|
|
|
|
|
//protects input and outputs, must be recursive because ao reentrance
|
|
|
|
std::recursive_mutex busy_update;
|
2015-07-27 21:20:44 -04:00
|
|
|
};
|
|
|
|
|
2015-07-27 22:05:35 -04:00
|
|
|
|
2015-08-03 01:38:38 -04:00
|
|
|
template<class OutputDataType = ReferenceCounter>
|
|
|
|
class VisualDataDistributor : public VisualProcessor<OutputDataType, OutputDataType> {
|
2015-07-27 22:05:35 -04:00
|
|
|
protected:
|
2015-07-31 21:03:17 -04:00
|
|
|
void process() {
|
2016-07-06 15:23:59 -04:00
|
|
|
OutputDataType *inp;
|
|
|
|
while (VisualProcessor<OutputDataType, OutputDataType>::input->try_pop(inp)) {
|
|
|
|
|
2015-08-11 00:50:43 -04:00
|
|
|
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
|
2016-07-06 15:23:59 -04:00
|
|
|
if (inp) {
|
|
|
|
inp->decRefCount();
|
|
|
|
}
|
2015-08-11 00:50:43 -04:00
|
|
|
return;
|
|
|
|
}
|
2016-07-06 15:23:59 -04:00
|
|
|
|
2015-07-27 22:05:35 -04:00
|
|
|
if (inp) {
|
2015-08-03 01:38:38 -04:00
|
|
|
VisualProcessor<OutputDataType, OutputDataType>::distribute(inp);
|
2015-07-27 22:05:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-09-10 21:48:18 -04:00
|
|
|
|
|
|
|
template<class OutputDataType = ReferenceCounter>
|
|
|
|
class VisualDataReDistributor : public VisualProcessor<OutputDataType, OutputDataType> {
|
|
|
|
protected:
|
|
|
|
void process() {
|
2016-07-06 15:23:59 -04:00
|
|
|
OutputDataType *inp;
|
|
|
|
while (VisualProcessor<OutputDataType, OutputDataType>::input->try_pop(inp)) {
|
|
|
|
|
2015-09-10 21:48:18 -04:00
|
|
|
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
|
2016-07-06 15:23:59 -04:00
|
|
|
if (inp) {
|
|
|
|
inp->decRefCount();
|
|
|
|
}
|
2015-09-10 21:48:18 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inp) {
|
|
|
|
OutputDataType *outp = buffers.getBuffer();
|
|
|
|
(*outp) = (*inp);
|
|
|
|
inp->decRefCount();
|
|
|
|
VisualProcessor<OutputDataType, OutputDataType>::distribute(outp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReBuffer<OutputDataType> buffers;
|
|
|
|
};
|