USRP Hardware Driver and USRP Manual Version: 4.0.0.0-0-unknown
UHD and USRP Manual
 
Loading...
Searching...
No Matches
property_tree.ipp
Go to the documentation of this file.
1//
2// Copyright 2011,2014-2016 Ettus Research
3// Copyright 2018 Ettus Research, a National Instruments Company
4// Copyright 2019 Ettus Research, a National Instruments Brand
5//
6// SPDX-License-Identifier: GPL-3.0-or-later
7//
8
9#pragma once
10
11#include <uhd/exception.hpp>
12#include <typeindex>
13#include <vector>
14#include <memory>
15
16/***********************************************************************
17 * Implement templated property impl
18 **********************************************************************/
19namespace uhd { namespace /*anon*/ {
20
21template <typename T>
22class property_impl : public property<T>
23{
24public:
25 property_impl<T>(property_tree::coerce_mode_t mode) : _coerce_mode(mode)
26 {
27 if (_coerce_mode == property_tree::AUTO_COERCE) {
28 _coercer = DEFAULT_COERCER;
29 }
30 }
31
32 ~property_impl<T>(void)
33 {
34 /* NOP */
35 }
36
37 property<T>& set_coercer(const typename property<T>::coercer_type& coercer)
38 {
39 if (_coercer) {
40 uhd::assertion_error("cannot register more than one coercer for a property");
41 }
42 if (_coerce_mode == property_tree::MANUAL_COERCE)
44 "cannot register coercer for a manually coerced property");
45
46 _coercer = coercer;
47 return *this;
48 }
49
50 property<T>& set_publisher(const typename property<T>::publisher_type& publisher)
51 {
52 if (_publisher) {
54 "cannot register more than one publisher for a property");
55 }
56
57 _publisher = publisher;
58 return *this;
59 }
60
61 property<T>& add_desired_subscriber(
62 const typename property<T>::subscriber_type& subscriber)
63 {
64 _desired_subscribers.push_back(subscriber);
65 return *this;
66 }
67
68 property<T>& add_coerced_subscriber(
69 const typename property<T>::subscriber_type& subscriber)
70 {
71 _coerced_subscribers.push_back(subscriber);
72 return *this;
73 }
74
75 property<T>& update(void)
76 {
77 this->set(this->get());
78 return *this;
79 }
80
81 void _set_coerced(const T& value)
82 {
83 init_or_set_value(_coerced_value, value);
84 for (typename property<T>::subscriber_type& csub : _coerced_subscribers) {
85 csub(get_value_ref(_coerced_value)); // let errors propagate
86 }
87 }
88
89 property<T>& set(const T& value)
90 {
91 init_or_set_value(_value, value);
92 for (typename property<T>::subscriber_type& dsub : _desired_subscribers) {
93 dsub(get_value_ref(_value)); // let errors propagate
94 }
95 if (_coercer) {
96 _set_coerced(_coercer(get_value_ref(_value)));
97 } else {
98 if (_coerce_mode == property_tree::AUTO_COERCE)
99 uhd::assertion_error("coercer missing for an auto coerced property");
100 }
101 return *this;
102 }
103
104 property<T>& set_coerced(const T& value)
105 {
106 if (_coerce_mode == property_tree::AUTO_COERCE)
107 uhd::assertion_error("cannot set coerced value an auto coerced property");
108 _set_coerced(value);
109 return *this;
110 }
111
112 const T get(void) const
113 {
114 if (empty()) {
115 throw uhd::runtime_error("Cannot get() on an uninitialized (empty) property");
116 }
117 if (_publisher) {
118 return _publisher();
119 } else {
120 if (_coerced_value.get() == NULL
121 and _coerce_mode == property_tree::MANUAL_COERCE)
122 throw uhd::runtime_error(
123 "uninitialized coerced value for manually coerced attribute");
124 return get_value_ref(_coerced_value);
125 }
126 }
127
128 const T get_desired(void) const
129 {
130 if (_value.get() == NULL)
131 throw uhd::runtime_error(
132 "Cannot get_desired() on an uninitialized (empty) property");
133
134 return get_value_ref(_value);
135 }
136
137 bool empty(void) const
138 {
139 return !bool(_publisher) and _value.get() == NULL;
140 }
141
142private:
143 static T DEFAULT_COERCER(const T& value)
144 {
145 return value;
146 }
147
148 static void init_or_set_value(std::unique_ptr<T>& scoped_value, const T& init_val)
149 {
150 if (scoped_value.get() == NULL) {
151 scoped_value.reset(new T(init_val));
152 } else {
153 *scoped_value = init_val;
154 }
155 }
156
157 static const T& get_value_ref(const std::unique_ptr<T>& scoped_value)
158 {
159 if (scoped_value.get() == NULL)
160 throw uhd::assertion_error("Cannot use uninitialized property data");
161 return *scoped_value.get();
162 }
163
164 const property_tree::coerce_mode_t _coerce_mode;
165 std::vector<typename property<T>::subscriber_type> _desired_subscribers;
166 std::vector<typename property<T>::subscriber_type> _coerced_subscribers;
167 typename property<T>::publisher_type _publisher;
168 typename property<T>::coercer_type _coercer;
169 std::unique_ptr<T> _value;
170 std::unique_ptr<T> _coerced_value;
171};
172
173}} // namespace uhd::
174
175/***********************************************************************
176 * Implement templated methods for the property tree
177 **********************************************************************/
178namespace uhd {
179
180template <typename T>
182{
183 this->_create(path,
184 typename std::shared_ptr<property<T> >(new property_impl<T>(coerce_mode)),
185 std::type_index(typeid(T)));
186 return this->access<T>(path);
187}
188
189template <typename T>
191{
192 return *std::static_pointer_cast<property<T> >(
193 this->_access_with_type_check(path, std::type_index(typeid(T))));
194}
195
196template <typename T>
197typename std::shared_ptr<property<T> > property_tree::pop(const fs_path& path)
198{
199 return std::static_pointer_cast<property<T> >(this->_pop(path));
200}
201
202} // namespace uhd
property< T > & create(const fs_path &path, coerce_mode_t coerce_mode=AUTO_COERCE)
Create a new property entry in the tree.
Definition property_tree.ipp:181
std::shared_ptr< property< T > > pop(const fs_path &path)
Pop a property off the tree, and returns the property.
Definition property_tree.ipp:197
property< T > & access(const fs_path &path)
Get access to a property in the tree.
Definition property_tree.ipp:190
coerce_mode_t
Definition property_tree.hpp:219
@ AUTO_COERCE
Definition property_tree.hpp:219
@ MANUAL_COERCE
Definition property_tree.hpp:219
Definition property_tree.hpp:70
std::function< T(void)> publisher_type
Definition property_tree.hpp:73
std::function< T(const T &)> coercer_type
Definition property_tree.hpp:74
std::function< void(const T &)> subscriber_type
Definition property_tree.hpp:72
Definition build_info.hpp:12
Definition exception.hpp:49
Definition property_tree.hpp:200
Definition exception.hpp:133