USRP Hardware Driver and USRP Manual: expert_nodes.hpp Source File

| USRP Hardware Driver and USRP Manual Version: 4.8.0.makepkg-0-g308126a4 UHD and USRP Manual |

Loading...
Searching...
No Matches
expert_nodes.hpp
Go to the documentation of this file.
1//
2// Copyright 2016 Ettus Research
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
7
8#pragma once
9
10#include <uhd/config.hpp>
11#include <uhd/exception.hpp>
12#include <uhd/types/time_spec.hpp>
13#include <uhd/utils/dirty_tracked.hpp>
14#include <uhd/utils/noncopyable.hpp>
15#include <stdint.h>
16#include <boost/core/demangle.hpp>
17#include <functional>
18#include <iostream>
19#include <list>
20#include <memory>
21#include <mutex>
22#include <sstream>
23#include <thread>
24
25namespace uhd { namespace experts {
26
27 enum node_class_t { CLASS_WORKER, CLASS_DATA, CLASS_PROPERTY };
28 enum node_access_t { ACCESS_READER, ACCESS_WRITER };
29 enum node_author_t { AUTHOR_NONE, AUTHOR_USER, AUTHOR_EXPERT };
30
38 class dag_vertex_t : private uhd::noncopyable
39{
40public:
41 typedef std::function<void(std::string)> callback_func_t;
42
43 virtual ~dag_vertex_t() {}
44
45 // Getters for basic info about the node
46 inline node_class_t get_class() const
47 {
48 return _class;
49 }
50
51 inline const std::string& get_name() const
52 {
53 return _name;
54 }
55
56 virtual const std::string& get_dtype() const = 0;
57
58 virtual std::string to_string() const = 0;
59
60 // Graph resolution specific
61 virtual bool is_dirty() const = 0;
62 virtual void mark_clean() = 0;
63 virtual void force_dirty() = 0;
64 virtual void resolve() = 0;
65
66 // External callbacks
67 virtual void set_write_callback(const callback_func_t& func) = 0;
68 virtual bool has_write_callback() const = 0;
69 virtual void clear_write_callback() = 0;
70 virtual void set_read_callback(const callback_func_t& func) = 0;
71 virtual bool has_read_callback() const = 0;
72 virtual void clear_read_callback() = 0;
73
74protected:
75 dag_vertex_t(const node_class_t c, const std::string& n) : _class(c), _name(n) {}
76
77private:
78 const node_class_t _class;
79 const std::string _name;
80};
81
82 class data_node_printer
83{
84public:
85 // Generic implementation
86 template <typename data_t>
87 static std::string print(const data_t& val)
88 {
89 std::ostringstream os;
90 os << val;
91 return os.str();
92 }
93
94 static std::string print(const uint8_t& val)
95 {
96 std::ostringstream os;
97 os << int(val);
98 return os.str();
99 }
100
101 static std::string print(const time_spec_t time)
102 {
103 std::ostringstream os;
104 os << time.get_real_secs();
105 return os.str();
106 }
107};
108
127template <typename data_t>
128 class data_node_t : public dag_vertex_t
129{
130public:
131 // A data_node_t instance can have a type of CLASS_DATA or CLASS_PROPERTY
132 // In general a data node is a property if it can be accessed and modified
133 // from the outside world (of experts) using read and write callbacks. We
134 // assume that if a callback mutex is passed into the data node that it will
135 // be accessed from the outside and tag the data node as a PROPERTY.
136 data_node_t(const std::string& name, std::recursive_mutex* mutex = NULL)
137 : dag_vertex_t(mutex ? CLASS_PROPERTY : CLASS_DATA, name)
138 , _callback_mutex(mutex)
139 , _data()
140 , _author(AUTHOR_NONE)
141 {
142 }
143
144 data_node_t(
145 const std::string& name, const data_t& value, std::recursive_mutex* mutex = NULL)
146 : dag_vertex_t(mutex ? CLASS_PROPERTY : CLASS_DATA, name)
147 , _callback_mutex(mutex)
148 , _data(value)
149 , _author(AUTHOR_NONE)
150 {
151 }
152
153 // Basic info
154 const std::string& get_dtype() const override
155 {
156 static const std::string dtype(boost::core::demangle(typeid(data_t).name()));
157 return dtype;
158 }
159
160 std::string to_string() const override
161 {
162 return data_node_printer::print(get());
163 }
164
165 inline node_author_t get_author() const
166 {
167 return _author;
168 }
169
170 // Graph resolution specific
171 bool is_dirty() const override
172 {
173 return _data.is_dirty();
174 }
175
176 void mark_clean() override
177 {
178 _data.mark_clean();
179 }
180
181 void force_dirty() override
182 {
183 _data.force_dirty();
184 }
185
186 void resolve() override
187 {
188 // NOP
189 }
190
191 // Data node specific setters and getters (for the framework)
192 void set(const data_t& value)
193 {
194 _data = value;
195 _author = AUTHOR_EXPERT;
196 }
197
198 const data_t& get() const
199 {
200 return _data;
201 }
202
203 // Data node specific setters and getters (for external entities)
204 void commit(const data_t& value)
205 {
206 if (_callback_mutex == NULL)
207 throw uhd::assertion_error(
208 "node " + get_name() + " is missing the callback mutex");
209 std::lock_guard<std::recursive_mutex> lock(*_callback_mutex);
210 set(value);
211 _author = AUTHOR_USER;
212 if (is_dirty() and has_write_callback()) {
213 _wr_callback(
214 std::string(get_name())); // Put the name on the stack before calling
215 }
216 }
217
218 data_t retrieve() const
219 {
220 if (_callback_mutex == NULL)
221 throw uhd::assertion_error(
222 "node " + get_name() + " is missing the callback mutex");
223 std::lock_guard<std::recursive_mutex> lock(*_callback_mutex);
224 if (has_read_callback()) {
225 _rd_callback(std::string(get_name()));
226 }
227 return get();
228 }
229
230private:
231 // External callbacks
232 void set_write_callback(const callback_func_t& func) override
233 {
234 _wr_callback = func;
235 }
236
237 bool has_write_callback() const override
238 {
239 return bool(_wr_callback);
240 }
241
242 void clear_write_callback() override
243 {
244 _wr_callback = nullptr;
245 }
246
247 void set_read_callback(const callback_func_t& func) override
248 {
249 _rd_callback = func;
250 }
251
252 bool has_read_callback() const override
253 {
254 return bool(_rd_callback);
255 }
256
257 void clear_read_callback() override
258 {
259 _rd_callback = nullptr;
260 }
261
262 std::recursive_mutex* _callback_mutex;
263 callback_func_t _rd_callback;
264 callback_func_t _wr_callback;
265 dirty_tracked<data_t> _data;
266 node_author_t _author;
267};
268
277 class node_retriever_t
278{
279public:
280 virtual ~node_retriever_t() {}
281 virtual const dag_vertex_t& lookup(const std::string& name) const = 0;
282
283private:
284 friend class data_accessor_t;
285 virtual dag_vertex_t& retrieve(const std::string& name) const = 0;
286};
287
295 class data_accessor_t
296{
297public:
298 virtual ~data_accessor_t() {}
299
300 virtual bool is_reader() const = 0;
301 virtual bool is_writer() const = 0;
302 virtual dag_vertex_t& node() const = 0;
303
304protected:
305 data_accessor_t(const node_retriever_t& r, const std::string& n)
306 : _vertex(r.retrieve(n))
307 {
308 }
309 dag_vertex_t& _vertex;
310};
311
312template <typename data_t>
313 class data_accessor_base : public data_accessor_t
314{
315public:
316 ~data_accessor_base() override {}
317
318 bool is_reader() const override
319 {
320 return _access == ACCESS_READER;
321 }
322
323 bool is_writer() const override
324 {
325 return _access == ACCESS_WRITER;
326 }
327
328 inline bool is_dirty() const
329 {
330 return _datanode->is_dirty();
331 }
332
333 inline node_class_t get_class() const
334 {
335 return _datanode->get_class();
336 }
337
338 inline node_author_t get_author() const
339 {
340 return _datanode->get_author();
341 }
342
343protected:
344 data_accessor_base(
345 const node_retriever_t& r, const std::string& n, const node_access_t a)
346 : data_accessor_t(r, n), _datanode(NULL), _access(a)
347 {
348 _datanode = dynamic_cast<data_node_t<data_t>*>(&node());
349 if (_datanode == NULL) {
350 throw uhd::type_error("Expected data type for node " + n + " was "
351 + boost::core::demangle(typeid(data_t).name())
352 + " but got " + node().get_dtype());
353 }
354 }
355
356 data_node_t<data_t>* _datanode;
357 const node_access_t _access;
358
359private:
360 dag_vertex_t& node() const override
361 {
362 return _vertex;
363 }
364};
365
373template <typename data_t>
374 class data_reader_t : public data_accessor_base<data_t>
375{
376public:
377 data_reader_t(const node_retriever_t& retriever, const std::string& node)
378 : data_accessor_base<data_t>(retriever, node, ACCESS_READER)
379 {
380 }
381
382 inline const data_t& get() const
383 {
384 return data_accessor_base<data_t>::_datanode->get();
385 }
386
387 inline operator const data_t&() const
388 {
389 return get();
390 }
391
392 inline bool operator==(const data_t& rhs)
393 {
394 return get() == rhs;
395 }
396
397 inline bool operator!=(const data_t& rhs)
398 {
399 return !(get() == rhs);
400 }
401
402 friend std::ostream& operator<<(std::ostream& os, const data_reader_t& reader)
403 {
404 os << reader.get();
405 return os;
406 }
407};
408
416template <typename data_t>
417 class data_writer_t : public data_accessor_base<data_t>
418{
419public:
420 data_writer_t(const node_retriever_t& retriever, const std::string& node)
421 : data_accessor_base<data_t>(retriever, node, ACCESS_WRITER)
422 {
423 }
424
425 inline const data_t& get() const
426 {
427 return data_accessor_base<data_t>::_datanode->get();
428 }
429
430 inline operator const data_t&() const
431 {
432 return get();
433 }
434
435 inline bool operator==(const data_t& rhs)
436 {
437 return get() == rhs;
438 }
439
440 inline bool operator!=(const data_t& rhs)
441 {
442 return !(get() == rhs);
443 }
444
445 inline void set(const data_t& value)
446 {
447 data_accessor_base<data_t>::_datanode->set(value);
448 }
449
450 inline data_writer_t<data_t>& operator=(const data_t& value)
451 {
452 set(value);
453 return *this;
454 }
455
456 inline data_writer_t<data_t>& operator=(const data_writer_t<data_t>& value)
457 {
458 set(value.get());
459 return *this;
460 }
461};
462
473 class worker_node_t : public dag_vertex_t
474{
475public:
476 worker_node_t(const std::string& name) : dag_vertex_t(CLASS_WORKER, name) {}
477
478 // Worker node specific
479 std::list<std::string> get_inputs() const
480 {
481 std::list<std::string> retval;
482 for (data_accessor_t* acc : _inputs) {
483 retval.push_back(acc->node().get_name());
484 }
485 return retval;
486 }
487
488 std::list<std::string> get_outputs() const
489 {
490 std::list<std::string> retval;
491 for (data_accessor_t* acc : _outputs) {
492 retval.push_back(acc->node().get_name());
493 }
494 return retval;
495 }
496
497protected:
498 // This function is used to bind data accessors
499 // to this worker. Accessors can be read/write
500 // and the binding will ensure proper dependency
501 // handling.
502 void bind_accessor(data_accessor_t& accessor)
503 {
504 if (accessor.is_reader()) {
505 _inputs.push_back(&accessor);
506 } else if (accessor.is_writer()) {
507 _outputs.push_back(&accessor);
508 } else {
509 throw uhd::assertion_error("Invalid accessor type");
510 }
511 }
512
513private:
514 // Graph resolution specific
515 bool is_dirty() const override
516 {
517 bool inputs_dirty = false;
518 for (data_accessor_t* acc : _inputs) {
519 inputs_dirty |= acc->node().is_dirty();
520 }
521 return inputs_dirty;
522 }
523
524 void mark_clean() override
525 {
526 for (data_accessor_t* acc : _inputs) {
527 acc->node().mark_clean();
528 }
529 }
530
531 void force_dirty() override
532 {
533 for (data_accessor_t* acc : _outputs) {
534 acc->node().force_dirty();
535 }
536 }
537
538 void resolve() override = 0;
539
540 // Basic type info
541 const std::string& get_dtype() const override
542 {
543 static const std::string dtype = "<worker>";
544 return dtype;
545 }
546
547 std::string to_string() const override
548 {
549 return "<worker>";
550 }
551
552 // Workers don't have callbacks so implement stubs
553 void set_write_callback(const callback_func_t&) override {}
554 bool has_write_callback() const override
555 {
556 return false;
557 }
558 void clear_write_callback() override {}
559 void set_read_callback(const callback_func_t&) override {}
560 bool has_read_callback() const override
561 {
562 return false;
563 }
564 void clear_read_callback() override {}
565
566 std::list<data_accessor_t*> _inputs;
567 std::list<data_accessor_t*> _outputs;
568};
569
570}} // namespace uhd::experts
uhd::experts::dag_vertex_t
Definition expert_nodes.hpp:39
uhd::experts::dag_vertex_t::is_dirty
virtual bool is_dirty() const =0
uhd::experts::dag_vertex_t::set_write_callback
virtual void set_write_callback(const callback_func_t &func)=0
uhd::experts::dag_vertex_t::dag_vertex_t
dag_vertex_t(const node_class_t c, const std::string &n)
Definition expert_nodes.hpp:75
uhd::experts::dag_vertex_t::~dag_vertex_t
virtual ~dag_vertex_t()
Definition expert_nodes.hpp:43
uhd::experts::dag_vertex_t::has_read_callback
virtual bool has_read_callback() const =0
uhd::experts::dag_vertex_t::get_dtype
virtual const std::string & get_dtype() const =0
uhd::experts::dag_vertex_t::mark_clean
virtual void mark_clean()=0
uhd::experts::dag_vertex_t::has_write_callback
virtual bool has_write_callback() const =0
uhd::experts::dag_vertex_t::clear_read_callback
virtual void clear_read_callback()=0
uhd::experts::dag_vertex_t::to_string
virtual std::string to_string() const =0
uhd::experts::dag_vertex_t::callback_func_t
std::function< void(std::string)> callback_func_t
Definition expert_nodes.hpp:41
uhd::experts::dag_vertex_t::force_dirty
virtual void force_dirty()=0
uhd::experts::dag_vertex_t::resolve
virtual void resolve()=0
uhd::experts::dag_vertex_t::set_read_callback
virtual void set_read_callback(const callback_func_t &func)=0
uhd::experts::dag_vertex_t::clear_write_callback
virtual void clear_write_callback()=0
uhd::experts::dag_vertex_t::get_name
const std::string & get_name() const
Definition expert_nodes.hpp:51
uhd::experts::dag_vertex_t::get_class
node_class_t get_class() const
Definition expert_nodes.hpp:46
uhd::experts::data_accessor_base::is_reader
bool is_reader() const override
Definition expert_nodes.hpp:318
uhd::experts::data_accessor_base::_access
const node_access_t _access
Definition expert_nodes.hpp:357
uhd::experts::data_accessor_base::is_dirty
bool is_dirty() const
Definition expert_nodes.hpp:328
uhd::experts::data_accessor_base::get_author
node_author_t get_author() const
Definition expert_nodes.hpp:338
uhd::experts::data_accessor_base::~data_accessor_base
~data_accessor_base() override
Definition expert_nodes.hpp:316
uhd::experts::data_accessor_base::is_writer
bool is_writer() const override
Definition expert_nodes.hpp:323
uhd::experts::data_accessor_base::get_class
node_class_t get_class() const
Definition expert_nodes.hpp:333
uhd::experts::data_accessor_base::data_accessor_base
data_accessor_base(const node_retriever_t &r, const std::string &n, const node_access_t a)
Definition expert_nodes.hpp:344
uhd::experts::data_accessor_base::_datanode
data_node_t< data_t > * _datanode
Definition expert_nodes.hpp:356
uhd::experts::data_accessor_t
Definition expert_nodes.hpp:296
uhd::experts::data_accessor_t::_vertex
dag_vertex_t & _vertex
Definition expert_nodes.hpp:309
uhd::experts::data_accessor_t::is_writer
virtual bool is_writer() const =0
uhd::experts::data_accessor_t::data_accessor_t
data_accessor_t(const node_retriever_t &r, const std::string &n)
Definition expert_nodes.hpp:305
uhd::experts::data_accessor_t::node
virtual dag_vertex_t & node() const =0
uhd::experts::data_accessor_t::~data_accessor_t
virtual ~data_accessor_t()
Definition expert_nodes.hpp:298
uhd::experts::data_accessor_t::is_reader
virtual bool is_reader() const =0
uhd::experts::data_node_printer
Definition expert_nodes.hpp:83
uhd::experts::data_node_printer::print
static std::string print(const uint8_t &val)
Definition expert_nodes.hpp:94
uhd::experts::data_node_printer::print
static std::string print(const time_spec_t time)
Definition expert_nodes.hpp:101
uhd::experts::data_node_printer::print
static std::string print(const data_t &val)
Definition expert_nodes.hpp:87
uhd::experts::data_node_t
Definition expert_nodes.hpp:129
uhd::experts::data_node_t::data_node_t
data_node_t(const std::string &name, std::recursive_mutex *mutex=NULL)
Definition expert_nodes.hpp:136
uhd::experts::data_node_t::set
void set(const data_t &value)
Definition expert_nodes.hpp:192
uhd::experts::data_node_t::retrieve
data_t retrieve() const
Definition expert_nodes.hpp:218
uhd::experts::data_node_t::commit
void commit(const data_t &value)
Definition expert_nodes.hpp:204
uhd::experts::data_node_t::force_dirty
void force_dirty() override
Definition expert_nodes.hpp:181
uhd::experts::data_node_t::get
const data_t & get() const
Definition expert_nodes.hpp:198
uhd::experts::data_node_t::resolve
void resolve() override
Definition expert_nodes.hpp:186
uhd::experts::data_node_t::get_author
node_author_t get_author() const
Definition expert_nodes.hpp:165
uhd::experts::data_node_t::to_string
std::string to_string() const override
Definition expert_nodes.hpp:160
uhd::experts::data_node_t::get_dtype
const std::string & get_dtype() const override
Definition expert_nodes.hpp:154
uhd::experts::data_node_t::data_node_t
data_node_t(const std::string &name, const data_t &value, std::recursive_mutex *mutex=NULL)
Definition expert_nodes.hpp:144
uhd::experts::data_node_t::mark_clean
void mark_clean() override
Definition expert_nodes.hpp:176
uhd::experts::data_node_t::is_dirty
bool is_dirty() const override
Definition expert_nodes.hpp:171
uhd::experts::data_reader_t::get
const data_t & get() const
Definition expert_nodes.hpp:382
uhd::experts::data_reader_t::operator==
bool operator==(const data_t &rhs)
Definition expert_nodes.hpp:392
uhd::experts::data_reader_t::data_reader_t
data_reader_t(const node_retriever_t &retriever, const std::string &node)
Definition expert_nodes.hpp:377
uhd::experts::data_reader_t::operator!=
bool operator!=(const data_t &rhs)
Definition expert_nodes.hpp:397
uhd::experts::data_reader_t::operator<<
friend std::ostream & operator<<(std::ostream &os, const data_reader_t &reader)
Definition expert_nodes.hpp:402
uhd::experts::data_writer_t::get
const data_t & get() const
Definition expert_nodes.hpp:425
uhd::experts::data_writer_t::operator=
data_writer_t< data_t > & operator=(const data_t &value)
Definition expert_nodes.hpp:450
uhd::experts::data_writer_t::set
void set(const data_t &value)
Definition expert_nodes.hpp:445
uhd::experts::data_writer_t::operator=
data_writer_t< data_t > & operator=(const data_writer_t< data_t > &value)
Definition expert_nodes.hpp:456
uhd::experts::data_writer_t::operator!=
bool operator!=(const data_t &rhs)
Definition expert_nodes.hpp:440
uhd::experts::data_writer_t::operator==
bool operator==(const data_t &rhs)
Definition expert_nodes.hpp:435
uhd::experts::data_writer_t::data_writer_t
data_writer_t(const node_retriever_t &retriever, const std::string &node)
Definition expert_nodes.hpp:420
uhd::experts::node_retriever_t
Definition expert_nodes.hpp:278
uhd::experts::node_retriever_t::~node_retriever_t
virtual ~node_retriever_t()
Definition expert_nodes.hpp:280
uhd::experts::node_retriever_t::lookup
virtual const dag_vertex_t & lookup(const std::string &name) const =0
uhd::experts::node_retriever_t::data_accessor_t
friend class data_accessor_t
Definition expert_nodes.hpp:284
uhd::experts::worker_node_t::get_inputs
std::list< std::string > get_inputs() const
Definition expert_nodes.hpp:479
uhd::experts::worker_node_t::worker_node_t
worker_node_t(const std::string &name)
Definition expert_nodes.hpp:476
uhd::experts::worker_node_t::get_outputs
std::list< std::string > get_outputs() const
Definition expert_nodes.hpp:488
uhd::experts::worker_node_t::bind_accessor
void bind_accessor(data_accessor_t &accessor)
Definition expert_nodes.hpp:502
uhd::time_spec_t
Definition time_spec.hpp:31
uhd::time_spec_t::get_real_secs
double get_real_secs(void) const
config.hpp
dirty_tracked.hpp
exception.hpp
uhd::experts
Definition expert_container.hpp:16
uhd::experts::node_author_t
node_author_t
Definition expert_nodes.hpp:29
uhd::experts::AUTHOR_USER
@ AUTHOR_USER
Definition expert_nodes.hpp:29
uhd::experts::AUTHOR_EXPERT
@ AUTHOR_EXPERT
Definition expert_nodes.hpp:29
uhd::experts::AUTHOR_NONE
@ AUTHOR_NONE
Definition expert_nodes.hpp:29
uhd::experts::node_access_t
node_access_t
Definition expert_nodes.hpp:28
uhd::experts::ACCESS_WRITER
@ ACCESS_WRITER
Definition expert_nodes.hpp:28
uhd::experts::ACCESS_READER
@ ACCESS_READER
Definition expert_nodes.hpp:28
uhd::experts::node_class_t
node_class_t
Definition expert_nodes.hpp:27
uhd::experts::CLASS_WORKER
@ CLASS_WORKER
Definition expert_nodes.hpp:27
uhd::experts::CLASS_DATA
@ CLASS_DATA
Definition expert_nodes.hpp:27
uhd::experts::CLASS_PROPERTY
@ CLASS_PROPERTY
Definition expert_nodes.hpp:27
uhd
Definition build_info.hpp:12
uhd::noncopyable
boost::noncopyable noncopyable
Definition noncopyable.hpp:45
noncopyable.hpp
uhd::assertion_error
Definition exception.hpp:49
uhd::type_error
Definition exception.hpp:97
time_spec.hpp