aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/include/uhdlib/experts/expert_container.hpp
blob: c50e45847d07d19a539f19dc8343df51b97a8046 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//
// 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_CONTAINER_HPP
#define INCLUDED_UHD_EXPERTS_EXPERT_CONTAINER_HPP

#include <uhdlib/experts/expert_nodes.hpp>
#include <uhd/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/recursive_mutex.hpp>

namespace uhd { namespace experts {

    enum auto_resolve_mode_t {
        AUTO_RESOLVE_OFF,
        AUTO_RESOLVE_ON_READ,
        AUTO_RESOLVE_ON_WRITE,
        AUTO_RESOLVE_ON_READ_WRITE
    };

    class UHD_API expert_container : private boost::noncopyable, public node_retriever_t {
    public: //Methods
        typedef boost::shared_ptr<expert_container> sptr;

        virtual ~expert_container() {};

        /*!
         * Return the name of this container
         */
        virtual const std::string& get_name() const = 0;

        /*!
         * Resolves all the nodes in this expert graph.
         *
         * Dependency analysis is performed on the graph and nodes
         * are resolved in a topologically sorted order to ensure
         * that no nodes receive stale data.
         * Nodes and their dependencies are resolved only if they are
         * dirty i.e. their contained values have changed since the
         * last resolve.
         * This call requires an acyclic expert graph.
         *
         * \param force If true then ignore dirty state and resolve all nodes
         * \throws uhd::runtime_error if graph cannot be resolved
         */
        virtual void resolve_all(bool force = false) = 0;

        /*!
         * Resolves all the nodes that depend on the specified node.
         *
         * Dependency analysis is performed on the graph and nodes
         * are resolved in a topologically sorted order to ensure
         * that no nodes receive stale data.
         * Nodes and their dependencies are resolved only if they are
         * dirty i.e. their contained values have changed since the
         * last resolve.
         * This call requires an acyclic expert graph.
         *
         * \param node_name Name of the node to start resolving from
         * \throws uhd::lookup_error if node_name not in container
         * \throws uhd::runtime_error if graph cannot be resolved
         *
         */
        virtual void resolve_from(const std::string& node_name) = 0;

        /*!
         * Resolves all the specified node and all of its dependencies.
         *
         * Dependency analysis is performed on the graph and nodes
         * are resolved in a topologically sorted order to ensure
         * that no nodes receive stale data.
         * Nodes and their dependencies are resolved only if they are
         * dirty i.e. their contained values have changed since the
         * last resolve.
         * This call requires an acyclic expert graph.
         *
         * \param node_name Name of the node to resolve
         * \throws uhd::lookup_error if node_name not in container
         * \throws uhd::runtime_error if graph cannot be resolved
         *
         */
        virtual void resolve_to(const std::string& node_name) = 0;

        /*!
         * Return a node retriever object for this container
         */
        virtual const node_retriever_t& node_retriever() const = 0;

        /*!
         * Returns a DOT (graph description language) representation
         * of the expert graph. The output has labels for the node
         * name, node type (data or worker) and the underlying
         * data type for each node.
         *
         */
        virtual std::string to_dot() const = 0;

        /*!
         * Runs several sanity checks on the underlying graph to
         * flag dependency issues. Outputs of the checks are
         * logged to the console so UHD_EXPERTS_VERBOSE_LOGGING
         * must be enabled to see the results
         *
         */
        virtual void debug_audit() const = 0;

    private:
        /*!
         * Lookup a node with the specified name in the contained graph
         *
         * If the node is found, a reference to the node is returned.
         * If the node is not found, uhd::lookup_error is thrown
         * lookup can return a data or a worker node
         * \implements uhd::experts::node_retriever_t
         *
         * \param name Name of the node to find
         *
         */
        virtual const dag_vertex_t& lookup(const std::string& name) const = 0;
        virtual dag_vertex_t& retrieve(const std::string& name) const = 0;

        /*!
         * expert_factory is a friend of expert_container and
         * handles all operations that change the structure of
         * the underlying dependency graph.
         * The expert_container instance owns all data and worker
         * nodes and is responsible for release storage on destruction.
         * However, the expert_factory allocates storage for the
         * node and passes them into the expert_container using the
         * following "protected" API calls.
         *
         */
        friend class expert_factory;

        /*!
         * Creates an empty instance of expert_container with the
         * specified name.
         *
         * \param name Name of the container
         */
        static sptr make(const std::string& name);

        /*!
         * Returns a reference to the resolver mutex.
         *
         * The resolver mutex guarantees that external operations
         * to data-nodes are serialized with resolves of this
         * container.
         *
         */
        virtual boost::recursive_mutex& resolve_mutex() = 0;

        /*!
         * Add a data node to the expert graph
         *
         * \param data_node Pointer to a fully constructed data node object
         * \resolve_mode Auto resolve options: Choose from "disabled" and resolve on "read", "write" or "both"
         * \throws uhd::runtime_error if node already exists or is of a wrong type (recoverable)
         * \throws uhd::assertion_error for other failures (unrecoverable. will clear the graph)
         *
         */
        virtual void add_data_node(dag_vertex_t* data_node, auto_resolve_mode_t resolve_mode = AUTO_RESOLVE_OFF) = 0;

        /*!
         * Add a worker node to the expert graph
         *
         * \param worker Pointer to a fully constructed worker object
         * \throws uhd::runtime_error if worker already exists or is of a wrong type (recoverable)
         * \throws uhd::assertion_error for other failures (unrecoverable. will clear the graph)
         *
         */
        virtual void add_worker(worker_node_t* worker) = 0;

        /*!
         * Release all storage for this object. This will delete all contained
         * data and worker nodes and remove all dependency relationship and
         * resolve callbacks.
         *
         * The object will be restored to its newly constructed state. Will not
         * throw.
         */
        virtual void clear() = 0;
    };

}}

#endif /* INCLUDED_UHD_EXPERTS_EXPERT_CONTAINER_HPP */