USRP Hardware Driver and USRP Manual: property_tree.ipp Source File

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