USRP Hardware Driver and USRP Manual  Version: 4.1.0.4-3
UHD and USRP Manual
property.hpp
Go to the documentation of this file.
1 //
2 // Copyright 2019 Ettus Research, a National Instruments Brand
3 //
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 //
6 
7 #pragma once
8 
9 #include <uhd/exception.hpp>
11 #include <uhd/utils/cast.hpp>
13 #include <memory>
14 #include <string>
15 
16 
17 namespace uhd { namespace rfnoc {
18 
19 // Forward declaration, separates includes
20 class prop_accessor_t;
21 
26 {
27 public:
28  enum access_t {
29  NONE,
30  RO = 0x1,
31  RW = 0x3,
32  RWLOCKED = 0x5
34  };
35 
36  property_base_t(const std::string& id, const res_source_info& source_info)
37  : _id(id), _source_info(source_info)
38  {
39  if(_id.find(':') != std::string::npos) {
40  throw uhd::value_error("Property ID `" + _id + "' contains invalid character!");
41  }
42  }
43 
44  virtual ~property_base_t()
45  {
46  //nop
47  }
48 
50  const std::string& get_id() const
51  {
52  return _id;
53  }
54 
57  {
58  return _source_info;
59  }
60 
62  //
63  // If it's true, that means this property was recently changed, but changes
64  // have not propagated yet and still need resolving.
65  virtual bool is_dirty() const = 0;
66 
68  //
69  // If it's false, that means this property has a default value that should
70  // NOT be forwarded.
71  virtual bool is_valid() const = 0;
72 
74  bool read_access_granted() const
75  {
76  return static_cast<uint8_t>(_access_mode) & 0x1;
77  }
78 
80  bool write_access_granted() const
81  {
82  return static_cast<uint8_t>(_access_mode) & 0x2;
83  }
84 
87  {
88  return _access_mode;
89  }
90 
92  virtual bool equal(property_base_t* rhs) const = 0;
93 
95  //
96  // The copy must have the same type, value, and ID. However, it is often
97  // desirable to have a new source information, so that can be overridden.
98  //
99  // The cleanliness state of \p original is not preserved. The new property
100  // will have the same cleanliness state as any other new property.
101  //
102  virtual std::unique_ptr<property_base_t> clone(res_source_info)
103  {
104  throw uhd::not_implemented_error("Cloning is not available for this property.");
105  }
106 
107  virtual void force_dirty() = 0;
108 
117  virtual void set_from_str(const std::string& new_val_str) = 0;
118 
119 private:
120  friend class prop_accessor_t;
121 
123  virtual void mark_clean() = 0;
124 
126  virtual void forward(property_base_t* next_prop) = 0;
127 
129  //
130  // Note: This uses RTTI to evaluate type equality
131  virtual bool is_type_equal(property_base_t* other_prop) const = 0;
132 
133  /*** Attributes **********************************************************/
135  const std::string _id;
136 
138  const res_source_info _source_info;
139 
141  // write this.
142  access_t _access_mode = RO;
143 };
144 
148 template <typename data_t>
150 {
151 public:
153  using value_type = data_t;
154 
155  property_t(const std::string& id, data_t&& value, const res_source_info& source_info);
156 
157  property_t(
158  const std::string& id, const data_t& value, const res_source_info& source_info);
159 
160  property_t(const std::string& id, const res_source_info& source_info);
161 
162  property_t(const property_t<data_t>& prop) = default;
163 
165  //
166  // If true, this means the value was recently changed, but it wasn't marked
167  // clean yet.
168  bool is_dirty() const override
169  {
170  return _data.is_dirty();
171  }
172 
174  //
175  // If it's false, that means this property has a default value that should
176  // NOT be used.
177  bool is_valid() const override
178  {
179  return _valid;
180  }
181 
182  bool equal(property_base_t* rhs) const override
183  {
184  if (!is_type_equal(rhs)) {
185  return false;
186  }
187  return get() == dynamic_cast<property_t<data_t>*>(rhs)->get();
188  }
189 
190  std::unique_ptr<property_base_t> clone(res_source_info new_src_info) override
191  {
192  return std::unique_ptr<property_base_t>(
193  new property_t<data_t>(get_id(), get(), new_src_info));
194  }
195 
196  void set_from_str(const std::string& new_val_str) override
197  {
198  try {
199  set(uhd::cast::from_str<data_t>(new_val_str));
200  } catch (uhd::runtime_error& ex) {
201  throw uhd::runtime_error(
202  std::string("Property ") + get_id() + ":" + ex.what());
203  }
204  }
205 
207  // const res_source_info& get_src_info() const = 0;
208 
210  //
211  // \throws uhd::access_error if the current access mode is not RW or RWLOCKED
212  // \throws uhd::resolve_error if the property is RWLOCKED but the new value
213  // doesn't match
214  void set(const data_t& value)
215  {
216  if (write_access_granted()) {
217  _data = value;
218  _valid = true;
219  } else if (get_access_mode() == RWLOCKED) {
220  if (_data.get() != value) {
221  throw uhd::resolve_error(std::string("Attempting to overwrite property `")
222  + get_id() + "@" + get_src_info().to_string()
223  + "' with a new value after it was locked!");
224  }
225  } else {
226  throw uhd::access_error(std::string("Attempting to write to property `")
227  + get_id() + "' without access privileges!");
228  }
229  }
230 
231  void force_dirty() override
232  {
233  if (write_access_granted()) {
234  _data.force_dirty();
235  } else if (get_access_mode() == RWLOCKED) {
236  if (!_data.is_dirty()) {
237  throw uhd::resolve_error(std::string("Attempting to overwrite property `")
238  + get_id()
239  + "' with dirty flag after it was locked!");
240  }
241  } else {
242  throw uhd::access_error(std::string("Attempting to flag dirty property `")
243  + get_id() + "' without access privileges!");
244  }
245  }
246 
248  //
249  // \throws uhd::access_error if either the property is flagged as invalid,
250  // or if no read access was granted.
251  const data_t& get() const
252  {
253  if (!is_valid()) {
254  throw uhd::access_error(std::string("Attempting to read property `")
255  + get_id() + "@" + get_src_info().to_string()
256  + "' before it was initialized!");
257  }
258  if (read_access_granted()) {
259  return _data;
260  }
261  throw uhd::access_error(std::string("Attempting to read property `") + get_id()
262  + "' without access privileges!");
263  }
264 
265  operator const data_t&() const
266  {
267  return get();
268  }
269 
270  bool operator==(const data_t& rhs)
271  {
272  return get() == rhs;
273  }
274 
275  property_t<data_t>& operator=(const data_t& value)
276  {
277  set(value);
278  return *this;
279  }
280 
281 private:
282  void mark_clean() override
283  {
284  _data.mark_clean();
285  }
286 
287  void forward(property_base_t* next_prop) override
288  {
289  if (not _valid) {
290  throw uhd::resolve_error(
291  std::string("Unable to forward invalid property ") + get_id());
292  }
293  property_t<data_t>* prop_ptr = dynamic_cast<property_t<data_t>*>(next_prop);
294  if (prop_ptr == nullptr) {
295  throw uhd::type_error(std::string("Unable to cast property ")
296  + next_prop->get_id() + " to the same type as property "
297  + get_id());
298  }
299 
300  prop_ptr->set(get());
301  }
302 
303  bool is_type_equal(property_base_t* other_prop) const override
304  {
305  return dynamic_cast<property_t<data_t>*>(other_prop) != nullptr;
306  }
307 
308  dirty_tracked<data_t> _data;
309  bool _valid;
310 }; // class property_t
311 
312 }} /* namespace uhd::rfnoc */
313 
314 #include <uhd/rfnoc/property.ipp>
Definition: property.hpp:26
virtual void force_dirty()=0
virtual bool equal(property_base_t *rhs) const =0
Return true if rhs has the same type and value.
access_t
Definition: property.hpp:28
@ NONE
Neither reading nor writing to this property is permitted.
Definition: property.hpp:29
@ RWLOCKED
Definition: property.hpp:32
property_base_t(const std::string &id, const res_source_info &source_info)
Definition: property.hpp:36
virtual void set_from_str(const std::string &new_val_str)=0
virtual std::unique_ptr< property_base_t > clone(res_source_info)
Create a copy of this property.
Definition: property.hpp:102
virtual bool is_valid() const =0
Query this property's valid flag.
const res_source_info & get_src_info() const
Return the source info for this property.
Definition: property.hpp:56
access_t get_access_mode() const
Return the current access mode.
Definition: property.hpp:86
virtual ~property_base_t()
Definition: property.hpp:44
const std::string & get_id() const
Gets the ID (name) of this property.
Definition: property.hpp:50
bool write_access_granted() const
Returns true if this property can be written to.
Definition: property.hpp:80
bool read_access_granted() const
Returns true if this property can be read.
Definition: property.hpp:74
virtual bool is_dirty() const =0
Query this property's dirty flag.
Definition: property.hpp:150
void set(const data_t &value)
Returns the source info for the property.
Definition: property.hpp:214
bool is_dirty() const override
Returns the dirty state of this property.
Definition: property.hpp:168
property_t(const std::string &id, data_t &&value, const res_source_info &source_info)
Definition: property.ipp:10
const data_t & get() const
Get the value of this property.
Definition: property.hpp:251
bool is_valid() const override
Query this property's valid flag.
Definition: property.hpp:177
std::unique_ptr< property_base_t > clone(res_source_info new_src_info) override
Create a copy of this property.
Definition: property.hpp:190
void set_from_str(const std::string &new_val_str) override
Definition: property.hpp:196
data_t value_type
We want to be good C++ citizens.
Definition: property.hpp:153
bool operator==(const data_t &rhs)
Definition: property.hpp:270
property_t< data_t > & operator=(const data_t &value)
Definition: property.hpp:275
bool equal(property_base_t *rhs) const override
Return true if rhs has the same type and value.
Definition: property.hpp:182
void force_dirty() override
Definition: property.hpp:231
property_t(const property_t< data_t > &prop)=default
#define UHD_API
Definition: config.h:70
Definition: build_info.hpp:12
Definition: exception.hpp:169
Definition: exception.hpp:158
Definition: exception.hpp:282
Definition: res_source_info.hpp:18
Definition: exception.hpp:133
Definition: exception.hpp:97
Definition: exception.hpp:109