libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
property.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QI_PROPERTY_HPP_
8 #define _QI_PROPERTY_HPP_
9 
10 #include <boost/function.hpp>
11 #include <boost/thread/mutex.hpp>
12 #include <boost/variant.hpp>
13 #include <ka/mutablestore.hpp>
14 #include <qi/signal.hpp>
15 #include <qi/future.hpp>
16 #include <qi/strand.hpp>
17 
18 #ifdef _MSC_VER
19 # pragma warning( push )
20  // needs to have dll-interface to be used by clients
21 # pragma warning( disable: 4251 )
22  // non dll-interface class * used as base for dll-interface class
23 # pragma warning( disable: 4275 )
24 #endif
25 
26 namespace qi
27 {
31  {
32  public:
33  PropertyBase() = default;
34 
35  // NonCopyable
36  PropertyBase(const PropertyBase&) = delete;
37  PropertyBase& operator=(const PropertyBase&) = delete;
38 
39  virtual ~PropertyBase() = default;
40  virtual SignalBase* signal() = 0;
41  virtual FutureSync<void> setValue(AutoAnyReference value) = 0;
42  virtual FutureSync<AnyValue> value() const = 0;
43  };
44 
45  namespace util
46  {
47  // Used as a qi::Property::Setter to only store and dispatch a value if it was changed.
49  {
50  template<class T>
51  bool operator()(boost::reference_wrapper<T> ref_to_current_value, const T& newValue) const {
52  T& currentValue = ref_to_current_value;
53  if (currentValue != newValue)
54  {
55  currentValue = newValue;
56  return true;
57  }
58  return false;
59  }
60  };
61 
62  }
63 
64  template<typename T>
65  class PropertyImpl: public SignalF<void(const T&)>, public PropertyBase
66  {
67  public:
71  using Setter = boost::function<bool (boost::reference_wrapper<T>, const T&)>;
72  using Getter = boost::function<T(boost::reference_wrapper<const T>)>;
74  using PropertyType = T;
75 
84  PropertyImpl(Getter getter = Getter(), Setter setter = Setter(),
86 
89  PropertyImpl(ExecutionContext* execContext, Getter getter = Getter(), Setter setter = Setter(),
91 
92  PropertyImpl(AutoAnyReference defaultValue, Getter getter = Getter(), Setter setter = Setter(),
94 
97  PropertyImpl(AutoAnyReference defaultValue, ExecutionContext* execContext = nullptr,
98  Getter getter = Getter(), Setter setter = Setter(),
100 
101  virtual FutureSync<T> get() const = 0;
102  virtual FutureSync<void> set(const T& v) = 0;
103 
104  PropertyImpl<T>& operator=(const T& v) { this->set(v); return *this; }
105 
106  SignalBase* signal() override { return this; }
107 
108  protected:
112 
113  T getImpl() const;
114  void setImpl(const T& v);
115  };
116 
122  template<typename T>
123  class UnsafeProperty: public PropertyImpl<T>
124  {
125  public:
127  using Getter = typename ImplType::Getter;
128  using Setter = typename ImplType::Setter;
129 
130  UnsafeProperty(Getter getter = Getter(), Setter setter = Setter(),
132  : PropertyImpl<T>(std::move(getter), std::move(setter), std::move(onsubscribe))
133  {}
134 
135  UnsafeProperty(AutoAnyReference defaultValue, Getter getter = Getter(), Setter setter = Setter(),
137  : PropertyImpl<T>(std::move(defaultValue), std::move(getter), std::move(setter), std::move(onsubscribe))
138  {}
139 
140  UnsafeProperty<T>& operator=(const T& v) { this->set(v); return *this; }
141 
142  FutureSync<T> get() const override;
143  FutureSync<void> set(const T& v) override;
144 
145  SignalBase* signal() override { return this; }
147  FutureSync<AnyValue> value() const override;
148 
149  };
150 
156  template<typename T>
157  class Property: public PropertyImpl<T>
158  {
159  public:
161  using Getter = typename ImplType::Getter;
162  using Setter = typename ImplType::Setter;
163 
166  Property(Getter getter = Getter(), Setter setter = Setter(),
168  : PropertyImpl<T>(std::move(getter), std::move(setter), std::move(onsubscribe))
169  {}
170 
173  Property(Strand& strand,
174  Getter getter = Getter(),
175  Setter setter = Setter(),
177  : PropertyImpl<T>(&strand, std::move(getter), std::move(setter), std::move(onsubscribe))
178  , _strand{ &strand }
179  {
180  }
181 
184  Property(AutoAnyReference defaultValue, Getter getter = Getter(), Setter setter = Setter(),
186  : PropertyImpl<T>(std::move(defaultValue), std::move(getter), std::move(setter), std::move(onsubscribe))
187  {}
188 
192  Strand& strand,
193  Getter getter = Getter(),
194  Setter setter = Setter(),
196  : PropertyImpl<T>(std::move(defaultValue),
197  &strand,
198  std::move(getter),
199  std::move(setter),
200  std::move(onsubscribe))
201  , _strand{ &strand }
202  {
203  }
204 
205  ~Property() override;
206 
207  Property<T>& operator=(const T& v) { this->set(v); return *this; }
208 
209  FutureSync<T> get() const override;
210  FutureSync<void> set(const T& v) override;
211 
212  SignalBase* signal() override { return this; }
214  FutureSync<AnyValue> value() const override;
215 
216  private:
217  // This class has to have a Trackable member even though it holds a strand because it does not
218  // always own that strand, and thus it can not always join it before being destroyed. Tracking
219  // a member ensures that no stranded callback might be executed after it has been destroyed.
220  struct Tracked : public Trackable<Tracked> { using Trackable<Tracked>::destroy; };
221  mutable Tracked _tracked;
222 
223  Strand& strand() const;
224  void joinStrand() QI_NOEXCEPT(true);
225 
226  // TODO:
227  // Right now, mutable_store_t stores the Mutable first (the pointer in this case) which
228  // is the one that will be instanciated by the default constructor. But since Strand is
229  // neither copyable nor movable and mutable_store_t relies on boost::variant and boost::variant
230  // does not support in-place construction of its value, the Strand value can never be set to the
231  // mutable_store_t. So use ka::mutable_store_t once we are able to construct values in-place in
232  // it.
233  mutable boost::variant<Strand, Strand*> _strand;
234  };
235 
238  {
239  public:
250  template<typename... Args>
251  explicit GenericProperty(const AutoAnyReference& defaultValue, Args&&... args)
252  : Property<AnyValue>(defaultValue, ka::fwd<Args>(args)...)
253  , _type{ defaultValue.type() }
254  {
255  _setSignature(makeTupleSignature({ _type }));
256  }
257 
268  template<typename... Args>
269  explicit GenericProperty(TypeInterface* type, Args&&... args)
270  : GenericProperty(AnyValue{ type }, ka::fwd<Args>(args)...)
271  {
272  }
273 
274  GenericProperty& operator=(const AnyValue& v)
275  {
276  this->set(v);
277  return *this;
278  }
279 
281  {
282  return set(AnyValue(value, false, false));
283  }
284 
285  FutureSync<void> set(const AnyValue& v) override;
286 
287  qi::Signature signature() const override
288  {
289  return makeTupleSignature({ _type });
290  }
291 
292  private:
293  TypeInterface* _type;
294  };
295 
296 }
297 
299 
300 #ifdef _MSC_VER
301 # pragma warning( pop )
302 #endif
303 
304 #endif // _QITYPE_PROPERTY_HPP_
FutureSync< AnyValue > value() const override
Definition: property.hxx:145
void setValue(qi::Promise< R > &p, const boost::function< R()> &f)
GenericProperty & operator=(const AnyValue &v)
Definition: property.hpp:274
T getImpl() const
Definition: property.hxx:73
FutureSync< void > setValue(AutoAnyReference value) override
Definition: property.hxx:151
#define QI_API
Definition: api.hpp:33
SignalBase * signal() override
Definition: property.hpp:145
void _setSignature(const Signature &s)
typename ImplType::Getter Getter
Definition: property.hpp:161
Property(AutoAnyReference defaultValue, Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:184
Property(AutoAnyReference defaultValue, Strand &strand, Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:191
typename ImplType::Getter Getter
Definition: property.hpp:127
boost::function< qi::ServiceDirectoryProxy::Status(boost::reference_wrapper< const qi::ServiceDirectoryProxy::Status >)> Getter
Definition: property.hpp:72
~Property() override
Definition: property.hxx:125
UnsafeProperty(AutoAnyReference defaultValue, Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:135
#define QI_NOEXCEPT(cond)
Specify that a function may throw or not. Do nothing if noexcept is not available.
Definition: macro.hpp:318
typename ImplType::Setter Setter
Definition: property.hpp:162
FutureSync< void > setValue(AutoAnyReference value) override
Definition: property.hxx:118
boost::function< bool(boost::reference_wrapper< qi::ServiceDirectoryProxy::Status >, const qi::ServiceDirectoryProxy::Status &)> Setter
Definition: property.hpp:71
qi::Signature signature() const override
Definition: property.hpp:287
UnsafeProperty(Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:130
boost::function< Future< void >(bool)> OnSubscribers
Definition: signal.hpp:45
TypeInterface * type() const
GenericProperty(const AutoAnyReference &defaultValue, Args &&...args)
Definition: property.hpp:251
virtual FutureSync< void > set(const T &v)=0
FutureSync< void > set(const T &v) override
Definition: property.hxx:139
Type-erased property, simulating a typed property but using AnyValue.
Definition: property.hpp:237
UnsafeProperty< T > & operator=(const T &v)
Definition: property.hpp:140
PropertyImpl(Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hxx:29
Property(Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:166
qi::Signature makeTupleSignature(const std::vector< qi::AnyReference > &vgv, bool resolveDynamic=false, const std::string &name=std::string(), const std::vector< std::string > &names=std::vector< std::string >())
SignalBase * signal() override
Definition: property.hpp:106
bool operator()(boost::reference_wrapper< T > ref_to_current_value, const T &newValue) const
Definition: property.hpp:51
FutureSync< void > set(const T &v) override
Definition: property.hxx:105
PropertyImpl< T > & operator=(const T &v)
Definition: property.hpp:104
Object tracking by blocking destruction while shared pointers are present.
Definition: trackable.hpp:45
void setImpl(const T &v)
Definition: property.hxx:81
GenericProperty(TypeInterface *type, Args &&...args)
Definition: property.hpp:269
typename ImplType::Setter Setter
Definition: property.hpp:128
Property(Strand &strand, Getter getter=Getter(), Setter setter=Setter(), SignalBase::OnSubscribers onsubscribe=SignalBase::OnSubscribers())
Definition: property.hpp:173
Property< T > & operator=(const T &v)
Definition: property.hpp:207
FutureSync< AnyValue > value() const override
Definition: property.hxx:112
FutureSync< void > setValue(AutoAnyReference value) override
Definition: property.hpp:280
SignalBase * signal() override
Definition: property.hpp:212