aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/experts/expert_nodes.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/experts/expert_nodes.hpp')
-rw-r--r--host/lib/experts/expert_nodes.hpp472
1 files changed, 0 insertions, 472 deletions
diff --git a/host/lib/experts/expert_nodes.hpp b/host/lib/experts/expert_nodes.hpp
deleted file mode 100644
index 697ca19c3..000000000
--- a/host/lib/experts/expert_nodes.hpp
+++ /dev/null
@@ -1,472 +0,0 @@
-//
-// Copyright 2016 Ettus Research
-// Copyright 2018 Ettus Research, a National Instruments Company
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-#ifndef INCLUDED_UHD_EXPERTS_EXPERT_NODES_HPP
-#define INCLUDED_UHD_EXPERTS_EXPERT_NODES_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/exception.hpp>
-#include <uhd/utils/dirty_tracked.hpp>
-#include <uhd/types/time_spec.hpp>
-#include <boost/function.hpp>
-#include <boost/thread/recursive_mutex.hpp>
-#include <boost/thread.hpp>
-#include <boost/units/detail/utility.hpp>
-#include <memory>
-#include <list>
-#include <stdint.h>
-
-namespace uhd { namespace experts {
-
- enum node_class_t { CLASS_WORKER, CLASS_DATA, CLASS_PROPERTY };
- enum node_access_t { ACCESS_READER, ACCESS_WRITER };
- enum node_author_t { AUTHOR_NONE, AUTHOR_USER, AUTHOR_EXPERT };
-
- /*!---------------------------------------------------------
- * class dag_vertex_t
- *
- * This serves as the base class for all nodes in the expert
- * graph. Data nodes and workers are derived from this class.
- * ---------------------------------------------------------
- */
- class dag_vertex_t : private boost::noncopyable {
- public:
- typedef boost::function<void(std::string)> callback_func_t;
-
- virtual ~dag_vertex_t() {}
-
- // Getters for basic info about the node
- inline node_class_t get_class() const {
- return _class;
- }
-
- inline const std::string& get_name() const {
- return _name;
- }
-
- virtual const std::string& get_dtype() const = 0;
-
- virtual std::string to_string() const = 0;
-
- // Graph resolution specific
- virtual bool is_dirty() const = 0;
- virtual void mark_clean() = 0;
- virtual void resolve() = 0;
-
- // External callbacks
- virtual void set_write_callback(const callback_func_t& func) = 0;
- virtual bool has_write_callback() const = 0;
- virtual void clear_write_callback() = 0;
- virtual void set_read_callback(const callback_func_t& func) = 0;
- virtual bool has_read_callback() const = 0;
- virtual void clear_read_callback() = 0;
-
- protected:
- dag_vertex_t(const node_class_t c, const std::string& n):
- _class(c), _name(n) {}
-
- private:
- const node_class_t _class;
- const std::string _name;
- };
-
- class data_node_printer {
- public:
- //Generic implementation
- template<typename data_t>
- static std::string print(const data_t& val) {
- std::ostringstream os;
- os << val;
- return os.str();
- }
-
- static std::string print(const uint8_t& val) {
- std::ostringstream os;
- os << int(val);
- return os.str();
- }
-
- static std::string print(const time_spec_t time) {
- std::ostringstream os;
- os << time.get_real_secs();
- return os.str();
- }
- };
-
- /*!---------------------------------------------------------
- * class data_node_t
- *
- * The data node class hold a passive piece of data in the
- * expert graph. A data node is clean if its underlying data
- * is clean. Access to the underlying data is provided using
- * two methods:
- * 1. Special accessor classes (for R/W enforcement)
- * 2. External clients (via commit and retrieve). This access
- * is protected by the callback mutex.
- *
- * Requirements for data_t
- * - Must have a default constructor
- * - Must have a copy constructor
- * - Must have an assignment operator (=)
- * - Must have an equality operator (==)
- * ---------------------------------------------------------
- */
- template<typename data_t>
- class data_node_t : public dag_vertex_t {
- public:
- // A data_node_t instance can have a type of CLASS_DATA or CLASS_PROPERTY
- // In general a data node is a property if it can be accessed and modified
- // from the outside world (of experts) using read and write callbacks. We
- // assume that if a callback mutex is passed into the data node that it will
- // be accessed from the outside and tag the data node as a PROPERTY.
- data_node_t(const std::string& name, boost::recursive_mutex* mutex = NULL) :
- dag_vertex_t(mutex?CLASS_PROPERTY:CLASS_DATA, name), _callback_mutex(mutex), _data(), _author(AUTHOR_NONE) {}
-
- data_node_t(const std::string& name, const data_t& value, boost::recursive_mutex* mutex = NULL) :
- dag_vertex_t(mutex?CLASS_PROPERTY:CLASS_DATA, name), _callback_mutex(mutex), _data(value), _author(AUTHOR_NONE) {}
-
- // Basic info
- virtual const std::string& get_dtype() const {
- static const std::string dtype(
- boost::units::detail::demangle(typeid(data_t).name()));
- return dtype;
- }
-
- virtual std::string to_string() const {
- return data_node_printer::print(get());
- }
-
- inline node_author_t get_author() const {
- return _author;
- }
-
- // Graph resolution specific
- virtual bool is_dirty() const {
- return _data.is_dirty();
- }
-
- virtual void mark_clean() {
- _data.mark_clean();
- }
-
- void resolve() {
- //NOP
- }
-
- // Data node specific setters and getters (for the framework)
- void set(const data_t& value) {
- _data = value;
- _author = AUTHOR_EXPERT;
- }
-
- const data_t& get() const {
- return _data;
- }
-
- // Data node specific setters and getters (for external entities)
- void commit(const data_t& value) {
- if (_callback_mutex == NULL) throw uhd::assertion_error("node " + get_name() + " is missing the callback mutex");
- boost::lock_guard<boost::recursive_mutex> lock(*_callback_mutex);
- set(value);
- _author = AUTHOR_USER;
- if (is_dirty() and has_write_callback()) {
- _wr_callback(std::string(get_name())); //Put the name on the stack before calling
- }
- }
-
- const data_t retrieve() const {
- if (_callback_mutex == NULL) throw uhd::assertion_error("node " + get_name() + " is missing the callback mutex");
- boost::lock_guard<boost::recursive_mutex> lock(*_callback_mutex);
- if (has_read_callback()) {
- _rd_callback(std::string(get_name()));
- }
- return get();
- }
-
- private:
- // External callbacks
- virtual void set_write_callback(const callback_func_t& func) {
- _wr_callback = func;
- }
-
- virtual bool has_write_callback() const {
- return not _wr_callback.empty();
- }
-
- virtual void clear_write_callback() {
- _wr_callback.clear();
- }
-
- virtual void set_read_callback(const callback_func_t& func) {
- _rd_callback = func;
- }
-
- virtual bool has_read_callback() const {
- return not _rd_callback.empty();
- }
-
- virtual void clear_read_callback() {
- _rd_callback.clear();
- }
-
- boost::recursive_mutex* _callback_mutex;
- callback_func_t _rd_callback;
- callback_func_t _wr_callback;
- dirty_tracked<data_t> _data;
- node_author_t _author;
- };
-
- /*!---------------------------------------------------------
- * class node_retriever_t
- *
- * Node storage is managed by a framework class so we need
- * and interface to find and retrieve data nodes to associate
- * with accessors.
- * ---------------------------------------------------------
- */
- class node_retriever_t {
- public:
- virtual ~node_retriever_t() {}
- virtual const dag_vertex_t& lookup(const std::string& name) const = 0;
- private:
- friend class data_accessor_t;
- virtual dag_vertex_t& retrieve(const std::string& name) const = 0;
- };
-
- /*!---------------------------------------------------------
- * class data_accessor_t
- *
- * Accessors provide protected access to data nodes and help
- * establish dependency relationships.
- * ---------------------------------------------------------
- */
- class data_accessor_t {
- public:
- virtual ~data_accessor_t() {}
-
- virtual bool is_reader() const = 0;
- virtual bool is_writer() const = 0;
- virtual dag_vertex_t& node() const = 0;
- protected:
- data_accessor_t(const node_retriever_t& r, const std::string& n):
- _vertex(r.retrieve(n)) {}
- dag_vertex_t& _vertex;
- };
-
- template<typename data_t>
- class data_accessor_base : public data_accessor_t {
- public:
- virtual ~data_accessor_base() {}
-
- virtual bool is_reader() const {
- return _access == ACCESS_READER;
- }
-
- virtual bool is_writer() const {
- return _access == ACCESS_WRITER;
- }
-
- inline bool is_dirty() const {
- return _datanode->is_dirty();
- }
-
- inline node_class_t get_class() const {
- return _datanode->get_class();
- }
-
- inline node_author_t get_author() const {
- return _datanode->get_author();
- }
-
- protected:
- data_accessor_base(
- const node_retriever_t& r, const std::string& n, const node_access_t a) :
- data_accessor_t(r, n), _datanode(NULL), _access(a)
- {
- _datanode = dynamic_cast< data_node_t<data_t>* >(&node());
- if (_datanode == NULL) {
- throw uhd::type_error("Expected data type for node " + n +
- " was " + boost::units::detail::demangle(typeid(data_t).name()) +
- " but got " + node().get_dtype());
- }
- }
-
- data_node_t<data_t>* _datanode;
- const node_access_t _access;
-
- private:
- virtual dag_vertex_t& node() const {
- return _vertex;
- }
- };
-
- /*!---------------------------------------------------------
- * class data_reader_t
- *
- * Accessor to read the value of a data node and to establish
- * a data node => worker node dependency
- * ---------------------------------------------------------
- */
- template<typename data_t>
- class data_reader_t : public data_accessor_base<data_t> {
- public:
- data_reader_t(const node_retriever_t& retriever, const std::string& node) :
- data_accessor_base<data_t>(
- retriever, node, ACCESS_READER) {}
-
- inline const data_t& get() const {
- return data_accessor_base<data_t>::_datanode->get();
- }
-
- inline operator const data_t&() const {
- return get();
- }
-
- inline bool operator==(const data_t& rhs) {
- return get() == rhs;
- }
-
- inline bool operator!=(const data_t& rhs) {
- return !(get() == rhs);
- }
- };
-
- /*!---------------------------------------------------------
- * class data_reader_t
- *
- * Accessor to read and write the value of a data node and
- * to establish a worker node => data node dependency
- * ---------------------------------------------------------
- */
- template<typename data_t>
- class data_writer_t : public data_accessor_base<data_t> {
- public:
- data_writer_t(const node_retriever_t& retriever, const std::string& node) :
- data_accessor_base<data_t>(
- retriever, node, ACCESS_WRITER) {}
-
- inline const data_t& get() const {
- return data_accessor_base<data_t>::_datanode->get();
- }
-
- inline operator const data_t&() const {
- return get();
- }
-
- inline bool operator==(const data_t& rhs) {
- return get() == rhs;
- }
-
- inline bool operator!=(const data_t& rhs) {
- return !(get() == rhs);
- }
-
- inline void set(const data_t& value) {
- data_accessor_base<data_t>::_datanode->set(value);
- }
-
- inline data_writer_t<data_t>& operator=(const data_t& value) {
- set(value);
- return *this;
- }
-
- inline data_writer_t<data_t>& operator=(const data_writer_t<data_t>& value) {
- set(value.get());
- return *this;
- }
-};
-
- /*!---------------------------------------------------------
- * class worker_node_t
- *
- * A node class to implement a function that consumes
- * zero or more input data nodes and emits zero or more output
- * data nodes. The worker can also operate on other non-expert
- * interfaces because worker_node_t is abstract and the client
- * is required to implement the "resolve" method in a subclass.
- * ---------------------------------------------------------
- */
- class worker_node_t : public dag_vertex_t {
- public:
- worker_node_t(const std::string& name) :
- dag_vertex_t(CLASS_WORKER, name) {}
-
- // Worker node specific
- std::list<std::string> get_inputs() const {
- std::list<std::string> retval;
- for(data_accessor_t* acc: _inputs) {
- retval.push_back(acc->node().get_name());
- }
- return retval;
- }
-
- std::list<std::string> get_outputs() const {
- std::list<std::string> retval;
- for(data_accessor_t* acc: _outputs) {
- retval.push_back(acc->node().get_name());
- }
- return retval;
- }
-
- protected:
- // This function is used to bind data accessors
- // to this worker. Accessors can be read/write
- // and the binding will ensure proper dependency
- // handling.
- void bind_accessor(data_accessor_t& accessor) {
- if (accessor.is_reader()) {
- _inputs.push_back(&accessor);
- } else if (accessor.is_writer()) {
- _outputs.push_back(&accessor);
- } else {
- throw uhd::assertion_error("Invalid accessor type");
- }
- }
-
- private:
- // Graph resolution specific
- virtual bool is_dirty() const {
- bool inputs_dirty = false;
- for(data_accessor_t* acc: _inputs) {
- inputs_dirty |= acc->node().is_dirty();
- }
- return inputs_dirty;
- }
-
- virtual void mark_clean() {
- for(data_accessor_t* acc: _inputs) {
- acc->node().mark_clean();
- }
- }
-
- virtual void resolve() = 0;
-
- // Basic type info
- virtual const std::string& get_dtype() const {
- static const std::string dtype = "<worker>";
- return dtype;
- }
-
- virtual std::string to_string() const {
- return "<worker>";
- }
-
- // Workers don't have callbacks so implement stubs
- virtual void set_write_callback(const callback_func_t&) {}
- virtual bool has_write_callback() const { return false; }
- virtual void clear_write_callback() {}
- virtual void set_read_callback(const callback_func_t&) {}
- virtual bool has_read_callback() const { return false; }
- virtual void clear_read_callback() {}
-
- std::list<data_accessor_t*> _inputs;
- std::list<data_accessor_t*> _outputs;
- };
-
-}}
-
-#endif /* INCLUDED_UHD_EXPERTS_EXPERT_NODE_HPP */