// Copyright (c) Charles J. Cliffe // SPDX-License-Identifier: GPL-2.0+ #pragma once #include "CubicSDRDefs.h" #include "ThreadQueue.h" #include "IOThread.h" #include template class VisualProcessor { public: virtual ~VisualProcessor() { } bool isInputEmpty() { std::lock_guard < std::recursive_mutex > busy_lock(busy_update); return input->empty(); } bool isOutputEmpty() { std::lock_guard < std::recursive_mutex > busy_lock(busy_update); for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if ((*outputs_i)->full()) { return false; } } return true; } bool isAnyOutputEmpty() { std::lock_guard < std::recursive_mutex > busy_lock(busy_update); for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if (!(*outputs_i)->full()) { return true; } } return false; } void setInput(ThreadQueue *vis_in) { std::lock_guard < std::recursive_mutex > busy_lock(busy_update); input = vis_in; } void attachOutput(ThreadQueue *vis_out) { // attach an output queue std::lock_guard < std::recursive_mutex > busy_lock(busy_update); outputs.push_back(vis_out); } void removeOutput(ThreadQueue *vis_out) { // remove an output queue std::lock_guard < std::recursive_mutex > busy_lock(busy_update); typename std::vector *>::iterator i = std::find(outputs.begin(), outputs.end(), vis_out); if (i != outputs.end()) { outputs.erase(i); } } void run() { std::lock_guard < std::recursive_mutex > busy_lock(busy_update); if (input && !input->empty()) { process(); } } protected: virtual void process() { // process inputs to output // distribute(output); } void distribute(OutputDataType *output) { // distribute outputs std::lock_guard < std::recursive_mutex > busy_lock(busy_update); output->setRefCount(outputs.size()); for (outputs_i = outputs.begin(); outputs_i != outputs.end(); outputs_i++) { if (!(*outputs_i)->push(output)) { output->decRefCount(); } } } ThreadQueue *input; std::vector *> outputs; typename std::vector *>::iterator outputs_i; //protects input and outputs, must be recursive because ao reentrance std::recursive_mutex busy_update; }; template class VisualDataDistributor : public VisualProcessor { protected: void process() { OutputDataType *inp; while (VisualProcessor::input->try_pop(inp)) { if (!VisualProcessor::isAnyOutputEmpty()) { if (inp) { inp->decRefCount(); } return; } if (inp) { VisualProcessor::distribute(inp); } } } }; template class VisualDataReDistributor : public VisualProcessor { protected: void process() { OutputDataType *inp; while (VisualProcessor::input->try_pop(inp)) { if (!VisualProcessor::isAnyOutputEmpty()) { if (inp) { inp->decRefCount(); } return; } if (inp) { OutputDataType *outp = buffers.getBuffer(); (*outp) = (*inp); inp->decRefCount(); VisualProcessor::distribute(outp); } } } ReBuffer buffers; };