USRP Hardware Driver and USRP Manual Version: 3.15.0.0-MacPorts-Release
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#ifndef INCLUDED_UHD_PROPERTY_TREE_IPP
10#define INCLUDED_UHD_PROPERTY_TREE_IPP
11
12#include <uhd/exception.hpp>
13#include <boost/foreach.hpp>
14#include <boost/scoped_ptr.hpp>
15#include <vector>
16
17/***********************************************************************
18 * Implement templated property impl
19 **********************************************************************/
20namespace uhd { namespace /*anon*/ {
21
22template <typename T>
23class property_impl : public property<T>
24{
25public:
26 property_impl<T>(property_tree::coerce_mode_t mode) : _coerce_mode(mode)
27 {
28 if (_coerce_mode == property_tree::AUTO_COERCE) {
29 _coercer = DEFAULT_COERCER;
30 }
31 }
32
33 ~property_impl<T>(void)
34 {
35 /* NOP */
36 }
37
38 property<T>& set_coercer(const typename property<T>::coercer_type& coercer)
39 {
40 if (not _coercer.empty())
41 uhd::assertion_error("cannot register more than one coercer for a property");
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 (not _publisher.empty())
54 "cannot register more than one publisher for a property");
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 BOOST_FOREACH (
84 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 BOOST_FOREACH (
93 typename property<T>::subscriber_type& dsub, _desired_subscribers) {
94 dsub(get_value_ref(_value)); // let errors propagate
95 }
96 if (not _coercer.empty()) {
97 _set_coerced(_coercer(get_value_ref(_value)));
98 } else {
99 if (_coerce_mode == property_tree::AUTO_COERCE)
100 uhd::assertion_error("coercer missing for an auto coerced property");
101 }
102 return *this;
103 }
104
105 property<T>& set_coerced(const T& value)
106 {
107 if (_coerce_mode == property_tree::AUTO_COERCE)
108 uhd::assertion_error("cannot set coerced value an auto coerced property");
109 _set_coerced(value);
110 return *this;
111 }
112
113 const T get(void) const
114 {
115 if (empty()) {
116 throw uhd::runtime_error("Cannot get() on an uninitialized (empty) property");
117 }
118 if (not _publisher.empty()) {
119 return _publisher();
120 } else {
121 if (_coerced_value.get() == NULL
122 and _coerce_mode == property_tree::MANUAL_COERCE)
123 throw uhd::runtime_error(
124 "uninitialized coerced value for manually coerced attribute");
125 return get_value_ref(_coerced_value);
126 }
127 }
128
129 const T get_desired(void) const
130 {
131 if (_value.get() == NULL)
132 throw uhd::runtime_error(
133 "Cannot get_desired() on an uninitialized (empty) property");
134
135 return get_value_ref(_value);
136 }
137
138 bool empty(void) const
139 {
140 return _publisher.empty() and _value.get() == NULL;
141 }
142
143private:
144 static T DEFAULT_COERCER(const T& value)
145 {
146 return value;
147 }
148
149 static void init_or_set_value(boost::scoped_ptr<T>& scoped_value, const T& init_val)
150 {
151 if (scoped_value.get() == NULL) {
152 scoped_value.reset(new T(init_val));
153 } else {
154 *scoped_value = init_val;
155 }
156 }
157
158 static const T& get_value_ref(const boost::scoped_ptr<T>& scoped_value)
159 {
160 if (scoped_value.get() == NULL)
161 throw uhd::assertion_error("Cannot use uninitialized property data");
162 return *scoped_value.get();
163 }
164
165 const property_tree::coerce_mode_t _coerce_mode;
166 std::vector<typename property<T>::subscriber_type> _desired_subscribers;
167 std::vector<typename property<T>::subscriber_type> _coerced_subscribers;
168 typename property<T>::publisher_type _publisher;
169 typename property<T>::coercer_type _coercer;
170 boost::scoped_ptr<T> _value;
171 boost::scoped_ptr<T> _coerced_value;
172};
173
174}} // namespace uhd::
175
176/***********************************************************************
177 * Implement templated methods for the property tree
178 **********************************************************************/
179namespace uhd {
180
181template <typename T>
183{
184 this->_create(path,
185 typename boost::shared_ptr<property<T> >(new property_impl<T>(coerce_mode)));
186 return this->access<T>(path);
187}
188
189template <typename T>
191{
192 return *boost::static_pointer_cast<property<T> >(this->_access(path));
193}
194
195template <typename T>
196typename boost::shared_ptr<property<T> > property_tree::pop(const fs_path& path)
197{
198 return boost::static_pointer_cast<property<T> >(this->_pop(path));
199}
200
201} // namespace uhd
202
203#endif /* INCLUDED_UHD_PROPERTY_TREE_IPP */
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:182
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
boost::shared_ptr< property< T > > pop(const fs_path &path)
Pop a property off the tree, and returns the property.
Definition property_tree.ipp:196
Definition property_tree.hpp:70
boost::function< T(void)> publisher_type
Definition property_tree.hpp:73
boost::function< void(const T &)> subscriber_type
Definition property_tree.hpp:72
boost::function< T(const T &)> coercer_type
Definition property_tree.hpp:74
Definition build_info.hpp:13
Definition exception.hpp:50
Definition property_tree.hpp:200
Definition exception.hpp:134