aboutsummaryrefslogtreecommitdiffstats
path: root/host/include
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2015-08-25 21:09:06 -0700
committerAshish Chaudhari <ashish@ettus.com>2016-02-11 14:36:20 -0800
commit27a08ccddc94c4945d48445b14c23fe6d186f9ef (patch)
treeaa0675904822e6dba9358cddc4ca1d66a3df3b7b /host/include
parent0d74d16093c9350205eb704b1aa6a4bcefa5667d (diff)
downloaduhd-27a08ccddc94c4945d48445b14c23fe6d186f9ef.tar.gz
uhd-27a08ccddc94c4945d48445b14c23fe6d186f9ef.tar.bz2
uhd-27a08ccddc94c4945d48445b14c23fe6d186f9ef.zip
prop_tree: Multiple API enhancements to uhd::property
- Added desired and coerced values and accessors to property - Added support to register desired subscribers - set APIs don't reallocate storage for a property value - Renamed callback method registration APIs - Registering 2 coercers or publishers for a property will throw - Registering a coercer and a publisher for the same property will throw
Diffstat (limited to 'host/include')
-rw-r--r--host/include/uhd/property_tree.hpp28
-rw-r--r--host/include/uhd/property_tree.ipp70
2 files changed, 78 insertions, 20 deletions
diff --git a/host/include/uhd/property_tree.hpp b/host/include/uhd/property_tree.hpp
index a92654ba2..ec65c73a0 100644
--- a/host/include/uhd/property_tree.hpp
+++ b/host/include/uhd/property_tree.hpp
@@ -42,31 +42,38 @@ public:
* Register a coercer into the property.
* A coercer is a special subscriber that coerces the value.
* Only one coercer may be registered per property.
- * Registering a coercer replaces the previous coercer.
* \param coercer the coercer callback function
* \return a reference to this property for chaining
*/
- virtual property<T> &coerce(const coercer_type &coercer) = 0;
+ virtual property<T> &set_coercer(const coercer_type &coercer) = 0;
/*!
* Register a publisher into the property.
* A publisher is a special callback the provides the value.
* Publishers are useful for creating read-only properties.
* Only one publisher may be registered per property.
- * Registering a publisher replaces the previous publisher.
* \param publisher the publisher callback function
* \return a reference to this property for chaining
*/
- virtual property<T> &publish(const publisher_type &publisher) = 0;
+ virtual property<T> &set_publisher(const publisher_type &publisher) = 0;
/*!
* Register a subscriber into the property.
- * All subscribers are called when the value changes.
+ * All desired subscribers are called when the value changes.
* Once a subscriber is registered, it cannot be unregistered.
* \param subscriber the subscriber callback function
* \return a reference to this property for chaining
*/
- virtual property<T> &subscribe(const subscriber_type &subscriber) = 0;
+ virtual property<T> &add_desired_subscriber(const subscriber_type &subscriber) = 0;
+
+ /*!
+ * Register a subscriber into the property.
+ * All coerced subscribers are called when the value changes.
+ * Once a subscriber is registered, it cannot be unregistered.
+ * \param subscriber the subscriber callback function
+ * \return a reference to this property for chaining
+ */
+ virtual property<T> &add_coerced_subscriber(const subscriber_type &subscriber) = 0;
/*!
* Update calls all subscribers w/ the current value.
@@ -89,7 +96,14 @@ public:
* otherwise an internal shadow is used for the value.
* \return the current value in the property
*/
- virtual T get(void) const = 0;
+ virtual const T get(void) const = 0;
+
+ /*!
+ * Get the current desired value of this property.
+ * A desired value does not defined if a property has a publisher.
+ * \return the current desired value in the property
+ */
+ virtual const T get_desired(void) const = 0;
/*!
* A property is empty if it has never been set.
diff --git a/host/include/uhd/property_tree.ipp b/host/include/uhd/property_tree.ipp
index 93962c963..171437450 100644
--- a/host/include/uhd/property_tree.ipp
+++ b/host/include/uhd/property_tree.ipp
@@ -20,6 +20,7 @@
#include <uhd/exception.hpp>
#include <boost/foreach.hpp>
+#include <boost/scoped_ptr.hpp>
#include <vector>
/***********************************************************************
@@ -34,18 +35,29 @@ public:
/* NOP */
}
- property<T> &coerce(const typename property<T>::coercer_type &coercer){
+ property<T> &set_coercer(const typename property<T>::coercer_type &coercer){
+ if (not _coercer.empty()) uhd::assertion_error("cannot register more than one coercer for a property");
+ if (not _publisher.empty()) uhd::assertion_error("cannot register a coercer and publisher for the same property");
+
_coercer = coercer;
return *this;
}
- property<T> &publish(const typename property<T>::publisher_type &publisher){
+ property<T> &set_publisher(const typename property<T>::publisher_type &publisher){
+ if (not _publisher.empty()) uhd::assertion_error("cannot register more than one publisher for a property");
+ if (not _coercer.empty()) uhd::assertion_error("cannot register a coercer and publisher for the same property");
+
_publisher = publisher;
return *this;
}
- property<T> &subscribe(const typename property<T>::subscriber_type &subscriber){
- _subscribers.push_back(subscriber);
+ property<T> &add_desired_subscriber(const typename property<T>::subscriber_type &subscriber){
+ _desired_subscribers.push_back(subscriber);
+ return *this;
+ }
+
+ property<T> &add_coerced_subscriber(const typename property<T>::subscriber_type &subscriber){
+ _coerced_subscribers.push_back(subscriber);
return *this;
}
@@ -55,16 +67,33 @@ public:
}
property<T> &set(const T &value){
- _value = boost::shared_ptr<T>(new T(_coercer.empty()? value : _coercer(value)));
- BOOST_FOREACH(typename property<T>::subscriber_type &subscriber, _subscribers){
- subscriber(*_value); //let errors propagate
+ init_or_set_value(_value, value);
+ BOOST_FOREACH(typename property<T>::subscriber_type &dsub, _desired_subscribers){
+ dsub(get_value_ref(_value)); //let errors propagate
+ }
+ if (not _coercer.empty()) {
+ init_or_set_value(_coerced_value, _coercer(get_value_ref(_value)));
+ }
+ BOOST_FOREACH(typename property<T>::subscriber_type &csub, _coerced_subscribers){
+ csub(get_value_ref(_coercer.empty() ? _value : _coerced_value)); //let errors propagate
}
return *this;
}
- T get(void) const{
+ const T get(void) const{
if (empty()) throw uhd::runtime_error("Cannot get() on an empty property");
- return _publisher.empty()? *_value : _publisher();
+ if (not _publisher.empty()) {
+ return _publisher();
+ } else {
+ return get_value_ref(_coercer.empty() ? _value : _coerced_value);
+ }
+ }
+
+ const T get_desired(void) const{
+ if (_value.get() == NULL) throw uhd::runtime_error("Cannot get_desired() on an empty property");
+ if (not _publisher.empty()) throw uhd::runtime_error("Cannot get_desired() on a property with a publisher");
+
+ return get_value_ref(_value);
}
bool empty(void) const{
@@ -72,10 +101,25 @@ public:
}
private:
- std::vector<typename property<T>::subscriber_type> _subscribers;
- typename property<T>::publisher_type _publisher;
- typename property<T>::coercer_type _coercer;
- boost::shared_ptr<T> _value;
+ static void init_or_set_value(boost::scoped_ptr<T>& scoped_value, const T& init_val) {
+ if (scoped_value.get() == NULL) {
+ scoped_value.reset(new T(init_val));
+ } else {
+ *scoped_value = init_val;
+ }
+ }
+
+ static const T& get_value_ref(const boost::scoped_ptr<T>& scoped_value) {
+ if (scoped_value.get() == NULL) throw uhd::assertion_error("Cannot use uninitialized property data");
+ return *static_cast<const T*>(scoped_value.get());
+ }
+
+ std::vector<typename property<T>::subscriber_type> _desired_subscribers;
+ std::vector<typename property<T>::subscriber_type> _coerced_subscribers;
+ typename property<T>::publisher_type _publisher;
+ typename property<T>::coercer_type _coercer;
+ boost::scoped_ptr<T> _value;
+ boost::scoped_ptr<T> _coerced_value;
};
}} //namespace uhd::/*anon*/