USRP Hardware Driver and USRP Manual Version: 4.7.0.0-0-unknown
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>
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
30
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
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>
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
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 {
163 }
164
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)
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)
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
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
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 }
310};
311
312template <typename data_t>
314{
315public:
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
339 {
340 return _datanode->get_author();
341 }
342
343protected:
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
358
359private:
360 dag_vertex_t& node() const override
361 {
362 return _vertex;
363 }
364};
365
373template <typename data_t>
374class 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 {
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>
417class 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 {
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 {
448 }
449
450 inline data_writer_t<data_t>& operator=(const data_t& value)
451 {
452 set(value);
453 return *this;
454 }
455
457 {
458 set(value.get());
459 return *this;
460 }
461};
462
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.
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
Definition expert_nodes.hpp:39
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:75
virtual ~dag_vertex_t()
Definition expert_nodes.hpp:43
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
virtual void force_dirty()=0
virtual void resolve()=0
std::function< void(std::string)> callback_func_t
Definition expert_nodes.hpp:41
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:51
node_class_t get_class() const
Definition expert_nodes.hpp:46
Definition expert_nodes.hpp:314
bool is_reader() const override
Definition expert_nodes.hpp:318
const node_access_t _access
Definition expert_nodes.hpp:357
bool is_dirty() const
Definition expert_nodes.hpp:328
node_author_t get_author() const
Definition expert_nodes.hpp:338
~data_accessor_base() override
Definition expert_nodes.hpp:316
bool is_writer() const override
Definition expert_nodes.hpp:323
node_class_t get_class() const
Definition expert_nodes.hpp:333
data_accessor_base(const node_retriever_t &r, const std::string &n, const node_access_t a)
Definition expert_nodes.hpp:344
data_node_t< data_t > * _datanode
Definition expert_nodes.hpp:356
Definition expert_nodes.hpp:296
dag_vertex_t & _vertex
Definition expert_nodes.hpp:309
virtual bool is_writer() const =0
data_accessor_t(const node_retriever_t &r, const std::string &n)
Definition expert_nodes.hpp:305
virtual dag_vertex_t & node() const =0
virtual ~data_accessor_t()
Definition expert_nodes.hpp:298
virtual bool is_reader() const =0
Definition expert_nodes.hpp:83
static std::string print(const uint8_t &val)
Definition expert_nodes.hpp:94
static std::string print(const time_spec_t time)
Definition expert_nodes.hpp:101
static std::string print(const data_t &val)
Definition expert_nodes.hpp:87
Definition expert_nodes.hpp:129
data_node_t(const std::string &name, std::recursive_mutex *mutex=NULL)
Definition expert_nodes.hpp:136
void set(const data_t &value)
Definition expert_nodes.hpp:192
data_t retrieve() const
Definition expert_nodes.hpp:218
void commit(const data_t &value)
Definition expert_nodes.hpp:204
void force_dirty() override
Definition expert_nodes.hpp:181
const data_t & get() const
Definition expert_nodes.hpp:198
void resolve() override
Definition expert_nodes.hpp:186
node_author_t get_author() const
Definition expert_nodes.hpp:165
std::string to_string() const override
Definition expert_nodes.hpp:160
const std::string & get_dtype() const override
Definition expert_nodes.hpp:154
data_node_t(const std::string &name, const data_t &value, std::recursive_mutex *mutex=NULL)
Definition expert_nodes.hpp:144
void mark_clean() override
Definition expert_nodes.hpp:176
bool is_dirty() const override
Definition expert_nodes.hpp:171
Definition expert_nodes.hpp:375
const data_t & get() const
Definition expert_nodes.hpp:382
bool operator==(const data_t &rhs)
Definition expert_nodes.hpp:392
data_reader_t(const node_retriever_t &retriever, const std::string &node)
Definition expert_nodes.hpp:377
bool operator!=(const data_t &rhs)
Definition expert_nodes.hpp:397
friend std::ostream & operator<<(std::ostream &os, const data_reader_t &reader)
Definition expert_nodes.hpp:402
Definition expert_nodes.hpp:418
const data_t & get() const
Definition expert_nodes.hpp:425
data_writer_t< data_t > & operator=(const data_t &value)
Definition expert_nodes.hpp:450
void set(const data_t &value)
Definition expert_nodes.hpp:445
data_writer_t< data_t > & operator=(const data_writer_t< data_t > &value)
Definition expert_nodes.hpp:456
bool operator!=(const data_t &rhs)
Definition expert_nodes.hpp:440
bool operator==(const data_t &rhs)
Definition expert_nodes.hpp:435
data_writer_t(const node_retriever_t &retriever, const std::string &node)
Definition expert_nodes.hpp:420
Definition expert_nodes.hpp:278
virtual ~node_retriever_t()
Definition expert_nodes.hpp:280
virtual const dag_vertex_t & lookup(const std::string &name) const =0
Definition expert_nodes.hpp:474
std::list< std::string > get_inputs() const
Definition expert_nodes.hpp:479
worker_node_t(const std::string &name)
Definition expert_nodes.hpp:476
std::list< std::string > get_outputs() const
Definition expert_nodes.hpp:488
void bind_accessor(data_accessor_t &accessor)
Definition expert_nodes.hpp:502
Definition time_spec.hpp:31
double get_real_secs(void) const
node_author_t
Definition expert_nodes.hpp:29
@ AUTHOR_USER
Definition expert_nodes.hpp:29
@ AUTHOR_EXPERT
Definition expert_nodes.hpp:29
@ AUTHOR_NONE
Definition expert_nodes.hpp:29
node_access_t
Definition expert_nodes.hpp:28
@ ACCESS_WRITER
Definition expert_nodes.hpp:28
@ ACCESS_READER
Definition expert_nodes.hpp:28
node_class_t
Definition expert_nodes.hpp:27
@ CLASS_WORKER
Definition expert_nodes.hpp:27
@ CLASS_DATA
Definition expert_nodes.hpp:27
@ CLASS_PROPERTY
Definition expert_nodes.hpp:27
Definition build_info.hpp:12
boost::noncopyable noncopyable
Definition noncopyable.hpp:45
Definition exception.hpp:48
Definition exception.hpp:96