30#include "factory/factory.hpp"
31#include "graphexceptions.hpp"
32#include "options/options.hpp"
33#include "portpolicy.hpp"
35#include "sharedstate.hpp"
36#include "streamports.hpp"
37#include "threadutilities.hpp"
38#include "yaml-cpp/yaml.h"
41GRAPHERROR(ProcessorInternalError);
42GRAPHERROR(ProcessingError);
43GRAPHERROR(ProcessingConfigureError);
44GRAPHERROR(ProcessingCreatePortsError);
45GRAPHERROR(ProcessingStreamInfoError);
46GRAPHERROR(ProcessingPrepareError);
47GRAPHERROR(ProcessingPreprocessingError);
49void convert_name(std::string& s);
64 IProcessor(ThreadPriority priority = PRIORITY_HIGH) : running_(
false), thread_() {
69 add_advanced_option(
"thread_core", thread_core_);
70 add_advanced_option(
"threadpriority", thread_priority_ = priority);
71 add_advanced_option(
"buffer_sizes", requested_buffer_sizes_);
74 virtual ~IProcessor() { internal_Stop(); }
78 static inline thread_local std::vector<TimingEntry>* t_metrics =
nullptr;
79 static constexpr size_t MAX_SAMPLES = 100000;
82 inline void record_metrics(uint64_t sync, uint64_t work)
noexcept {
83 if (!t_metrics) [[unlikely]] {
84 t_metrics =
new std::vector<TimingEntry>();
85 t_metrics->reserve(MAX_SAMPLES);
88 if (t_metrics->size() < MAX_SAMPLES) {
89 t_metrics->push_back({sync, work});
94 void dump_benchmarks() {
95 if (!t_metrics || t_metrics->empty())
return;
97 std::system(
"mkdir -p bench");
100 std::string filename =
"bench/bench_" + std::string(
name()) +
"_" +
101 std::to_string(
reinterpret_cast<uintptr_t
>(
this)) +
".bin";
103 std::ofstream f{filename, std::ios::binary};
106 f.write(
reinterpret_cast<const char*
>(t_metrics->data()),
110 LOG(ERROR) <<
"Failed to write binary to " << filename;
123 const std::string
name()
const {
return name_; }
131 const std::string
type()
const {
return type_; }
158 bool has_input_port(
const std::string& port) {
return input_ports_.count(port) == 1; }
165 bool has_output_port(
const std::string& port) {
return output_ports_.count(port) == 1; }
167 virtual bool issource()
const {
return n_input_ports() == 0; }
169 virtual bool isfilter()
const {
return (!issource() && !issink()); }
170 virtual bool isautonomous()
const {
return (issource() && issink()); }
172 ThreadPriority thread_priority()
const {
return thread_priority_(); }
173 ThreadCore thread_core()
const {
return thread_core_(); }
174 bool running()
const {
return running_.load(); }
176 YAML::Node ExportYAML();
178 void checkNonvoluntaryContextSwitches();
181 std::map<std::string, std::shared_ptr<std::ostream>> streams_;
182 std::vector<TimePoint> test_source_timestamps_;
186 void create_file(
const std::string& prefix,
const std::string& variable_name,
187 const std::string& extension =
"bin");
189 void prepare_latency_test(ProcessingContext& context);
190 void save_source_timestamps_to_disk(std::uint64_t n_timestamps);
214 template <
typename TValue>
216 bool required =
false) {
217 options_.add(std::move(
name), value, std::move(description), required);
238 template <
typename DATATYPE>
240 const typename DATATYPE::Parameters& parameters,
242 if (
name.size() == 0) {
243 name = DATATYPE::dataname();
246 if (output_ports_.count(
name) == 1) {
247 throw std::runtime_error(
"Output port name \"" +
name +
248 "\" is invalid or already exists.");
264 template <
typename DATATYPE>
280 template <
typename DATATYPE>
283 const typename DATATYPE::Capabilities& capabilities,
285 if (
name.size() == 0) {
286 name = DATATYPE::dataname();
289 if (input_ports_.count(
name) == 1) {
290 throw std::runtime_error(
"Input port name \"" +
name +
291 "\" is invalid or already exists.");
307 template <
typename DATATYPE>
405 template <
typename T>
407 Permission external = Permission::WRITE,
408 std::string description =
"") {
411 state, default_value, Permission::READ, external, description));
414 state, default_value, Permission::NONE, external, description));
439 template <
typename T>
441 bool cooperative =
false,
442 Permission external = Permission::READ,
443 std::string description =
"") {
446 state, default_value, Permission::WRITE, external, description));
449 state, default_value, Permission::NONE, external, description));
471 template <
typename T>
473 Permission external = Permission::NONE,
474 std::string description =
"") {
476 state, default_value, Permission::READ, external, description));
498 template <
typename T>
500 Permission external = Permission::NONE,
501 std::string description =
"") {
503 state, default_value, Permission::WRITE, external, description));
524 template <
typename T>
526 Permission peers = Permission::WRITE,
527 Permission external = Permission::NONE,
528 std::string description =
"") {
529 if (shared_states_.count(state) == 1) {
530 throw ProcessorInternalError(
531 "Shared state \"" + state +
"\" is invalid or already exists.",
name());
534 shared_states_[state] = std::unique_ptr<IState>(
558 template <
typename T>
560 Permission peers = Permission::READ,
561 Permission external = Permission::NONE,
562 std::string description =
"") {
563 if (shared_states_.count(state) == 1) {
564 throw ProcessorInternalError(
565 "Shared state \"" + state +
"\" is invalid or already exists.",
name());
568 shared_states_[state] = std::unique_ptr<IState>(
579 if (this->shared_states_.count(state) == 0) {
580 throw ProcessorInternalError(
"Shared state \"" + state +
"\" does not exist.",
name());
582 return shared_states_[state];
586 void expose_method(
const std::string& methodname, YAML::Node (T::*method)(
const YAML::Node&)) {
587 if (exposed_methods_.count(methodname) == 1) {
588 throw ProcessorInternalError(
589 "Exposed method \"" + methodname +
"\" is invalid or already exists.",
name());
591 exposed_methods_[methodname] =
592 std::bind(method,
static_cast<T*
>(
this), std::placeholders::_1);
595 std::function<YAML::Node(
const YAML::Node&)>& exposed_method(
const std::string& method) {
596 if (this->exposed_methods_.count(method) == 0) {
597 throw ProcessorInternalError(
"Exposed method \"" + method +
"\" does not exist.",
600 return exposed_methods_[method];
604 virtual std::string default_input_port()
const;
605 virtual std::string default_output_port()
const;
608 virtual void Configure(
const GlobalContext& _) {}
609 virtual void CreatePorts() = 0;
610 virtual void Preprocess(ProcessingContext& _) {}
611 virtual void Process(ProcessingContext& context) = 0;
612 virtual void Postprocess(ProcessingContext& _) {}
613 virtual void CompleteStreamInfo();
614 virtual void Prepare(GlobalContext& _) {}
615 virtual void Unprepare(GlobalContext& _) {}
616 virtual void TestPrepare(ProcessingContext& _) {}
617 virtual void TestFinalize(ProcessingContext& _) {}
620 void internal_Configure(
const YAML::Node& node,
621 const GlobalContext& context);
622 void internal_CreatePorts();
623 void internal_PrepareConnectionIn(SlotAddress& in);
624 void internal_PrepareConnectionOut(SlotAddress& out);
625 void internal_ConnectIn(
const SlotAddress& address, IProcessor* upstream,
626 const SlotAddress& upstream_address);
627 void internal_ConnectOut(
const SlotAddress& address, IProcessor* downstream,
628 const SlotAddress& downstream_address);
630 void internal_NegotiateConnections();
632 void internal_CreateRingBuffers();
633 void internal_PrepareProcessing();
635 void internal_ThreadEntry(RunContext& runcontext);
637 void internal_Start(RunContext& runcontext);
638 void internal_Stop();
640 void internal_Alert();
642 YAML::Node internal_ApplyMethod(
const std::string&
name,
const YAML::Node& node);
644 void set_name_and_type(std::string
name, std::string
type) {
645 name_ = std::move(
name);
646 type_ = std::move(
type);
649 template <
typename TValue>
650 void add_advanced_option(std::string
name, TValue& value, std::string description =
"",
651 bool required =
false) {
652 advanced_options_.add(std::move(
name), value, std::move(description), required);
659 std::map<std::string, std::unique_ptr<IPortIn>> input_ports_;
660 std::map<std::string, std::unique_ptr<IPortOut>> output_ports_;
662 std::map<std::string, std::function<YAML::Node(
const YAML::Node&)>> exposed_methods_;
663 std::map<std::string, std::shared_ptr<IState>> shared_states_;
665 bool negotiated_ =
false;
666 bool prepared_ =
false;
668 std::atomic<bool> running_;
672 options::Value<ThreadPriority, false> thread_priority_{
673 PRIORITY_HIGH, options::inrange<ThreadPriority>(PRIORITY_NONE, PRIORITY_HIGH)};
675 options::Value<ThreadCore, false> thread_core_{
676 CORE_NOT_PINNED, options::inrange<ThreadCore>(
677 CORE_NOT_PINNED, (ThreadCore) sysconf(_SC_NPROCESSORS_ONLN) - 1)};
679 options::NullableBool new_test_flag_;
680 options::Value<std::map<std::string, int>> requested_buffer_sizes_{};
685 uint64_t lastNonvoluntaryContextSwitches = 0;
688 options::OptionList options_;
689 options::OptionList advanced_options_;
692typedef std::map<std::string, std::pair<std::string, std::unique_ptr<IProcessor>>> ProcessorMap;
694typedef factory::ObjectFactory<IProcessor, std::string> ProcessorFactory;
696template <
class PROCESSOR>
697class ProcessorRegistrar {
699 ProcessorRegistrar(std::string name);
702template <
class PROCESSOR>
703ProcessorRegistrar<PROCESSOR>::ProcessorRegistrar(std::string name) {
704 ProcessorFactory::instance().registerClass(name,
705 factory::createInstance<IProcessor, PROCESSOR>);
708#define REGISTERPROCESSOR(PROCESSOR) \
710 static ProcessorRegistrar<PROCESSOR> _registrar(#PROCESSOR); \
Definition istreamports.hpp:184
Definition istreamports.hpp:87
PortOut< DATATYPE > * create_output_port(std::string name, const typename DATATYPE::Parameters ¶meters, const PortOutPolicy &policy)
Definition iprocessor.hpp:239
PortOut< DATATYPE > * create_output_port(const typename DATATYPE::Parameters ¶meters, const PortOutPolicy &policy)
Definition iprocessor.hpp:265
bool has_output_port(const std::string &port)
Definition iprocessor.hpp:165
void add_option(std::string name, TValue &value, std::string description="", bool required=false)
Definition iprocessor.hpp:215
StaticState< T > * create_static_state(std::string state, T default_value, bool shared=true, Permission external=Permission::WRITE, std::string description="")
Definition iprocessor.hpp:406
WritableState< T > * create_writable_shared_state(const std::string &state, T default_value, Permission peers=Permission::READ, Permission external=Permission::NONE, std::string description="")
Definition iprocessor.hpp:559
unsigned int n_output_ports() const
Definition iprocessor.hpp:141
BroadcasterState< T > * create_broadcaster_state(std::string state, T default_value, Permission external=Permission::NONE, std::string description="")
Definition iprocessor.hpp:472
const std::string type() const
Definition iprocessor.hpp:131
IPortOut * output_port(const std::string &port)
Definition iprocessor.hpp:325
const std::set< std::string > input_port_names() const
Definition iprocessor.cpp:40
FollowerState< T > * create_follower_state(std::string state, T default_value, Permission external=Permission::NONE, std::string description="")
Definition iprocessor.hpp:499
ISlotOut * output_slot(const SlotAddress &address)
Definition iprocessor.cpp:99
const std::set< std::string > output_port_names() const
Definition iprocessor.cpp:48
ReadableState< T > * create_readable_shared_state(const std::string &state, T default_value, Permission peers=Permission::WRITE, Permission external=Permission::NONE, std::string description="")
Definition iprocessor.hpp:525
unsigned int n_input_ports() const
Definition iprocessor.hpp:136
bool has_input_port(const std::string &port)
Definition iprocessor.hpp:158
std::shared_ptr< IState > shared_state(const std::string &state)
Definition iprocessor.hpp:578
ISlotIn * input_slot(const SlotAddress &address)
Definition iprocessor.cpp:95
IPortIn * input_port(const std::string &port)
Definition iprocessor.hpp:318
PortIn< DATATYPE > * create_input_port(std::string name, const typename DATATYPE::Capabilities &capabilities, const PortInPolicy &policy)
Definition iprocessor.hpp:282
PortIn< DATATYPE > * create_input_port(const typename DATATYPE::Capabilities &capabilities, const PortInPolicy &policy)
Definition iprocessor.hpp:308
ProducerState< T > * create_producer_state(std::string state, T default_value, bool cooperative=false, Permission external=Permission::READ, std::string description="")
Definition iprocessor.hpp:440
void remove_option(const std::string &name)
Definition iprocessor.cpp:83
const std::string name() const
Definition iprocessor.hpp:123
Definition istreamports.hpp:126
Definition istreamports.hpp:40
Definition sharedstate.hpp:138
Definition connections.hpp:24
Definition portpolicy.hpp:43
Definition streamports.hpp:256
Definition portpolicy.hpp:54
Definition streamports.hpp:98
Definition sharedstate.hpp:192
Definition connections.hpp:54
Definition sharedstate.hpp:332
Definition processorgraph.hpp:62
Definition iprocessor.hpp:50