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