diff options
author | Ashish Chaudhari <ashish@ettus.com> | 2015-08-25 21:09:06 -0700 |
---|---|---|
committer | Ashish Chaudhari <ashish@ettus.com> | 2016-02-11 14:36:20 -0800 |
commit | 27a08ccddc94c4945d48445b14c23fe6d186f9ef (patch) | |
tree | aa0675904822e6dba9358cddc4ca1d66a3df3b7b /host/include | |
parent | 0d74d16093c9350205eb704b1aa6a4bcefa5667d (diff) | |
download | uhd-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.hpp | 28 | ||||
-rw-r--r-- | host/include/uhd/property_tree.ipp | 70 |
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*/ |