libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proxyproperty.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_TYPE_PROXYPROPERTY_HPP_
8 #define _QI_TYPE_PROXYPROPERTY_HPP_
9 
10 #include <qi/log.hpp>
11 #include <qi/property.hpp>
12 #include <qi/anyfunction.hpp>
13 
14 
15 namespace qi
16 {
21  template < typename T, template< class...> class PropertyType = Property >
22  class ProxyProperty: public PropertyType<T>
23  {
24  public:
28  /* The signal bounce code is completely duplicated from SignalProxy.
29  * Unfortunately factoring this is not trivial:
30  * onSubscribe needs to be passed to Signal constructor, and we want to keep
31  * it that way.
32  */
33  ProxyProperty(AnyObject object, const std::string& propertyName)
34  {
35  setup(object, propertyName);
36  }
37  void setup(AnyObject object, const std::string& propertyName);
39  Future<void> onSubscribe(bool enable, GenericObject* object, const std::string& propertyName, SignalLink link);
41  void triggerOverride(const GenericFunctionParameters& params, MetaCallType, GenericObject* object, const std::string& propertyName);
42  private:
43  T getter(GenericObject* object, const std::string& propertyName);
44  bool setter(T&, const T&, GenericObject* object, const std::string& propertyName);
45  };
46 
47  template<typename T, template< class...> class PropertyType>
48  void makeProxyProperty(PropertyType<T>& target, AnyObject object, const std::string& signalName)
49  {
50  ProxyProperty<T, PropertyType>& proxy = static_cast<ProxyProperty<T, PropertyType> &>(target);
51  proxy.setup(object, signalName);
52  }
53  template<typename T, template< class...> class PropertyType>
54  void makeProxyProperty(ProxyProperty<T, PropertyType>& target, AnyObject object, const std::string& signalName)
55  {
56  target.setup(object, signalName);
57  }
58 
59  template<typename T, template< class...> class PropertyType>
61  {
62  SignalType::disconnectAll();
63  }
64 
65  template<typename T, template< class...> class PropertyType>
66  void ProxyProperty<T, PropertyType>::setup(AnyObject object, const std::string& propertyName)
67  {
68  // signal part
69  SignalBase::setOnSubscribers(boost::bind(&ThisProxyType::onSubscribe, this, _1,
70  object.asGenericObject(), propertyName, SignalBase::invalidSignalLink));
71  SignalBase::setTriggerOverride(boost::bind(&ThisProxyType::triggerOverride, this, _1, _2,
72  object.asGenericObject(), propertyName));
73 
74  // property part
75  this->_getter = boost::bind(&ThisProxyType::getter, this, object.asGenericObject(), propertyName);
76  this->_setter = boost::bind(&ThisProxyType::setter, this, _1, _2, object.asGenericObject(), propertyName);
77  }
78 
79  template<typename T, template< class...> class PropertyType>
80  Future<void> ProxyProperty<T, PropertyType>::onSubscribe(bool enable, GenericObject* object, const std::string& propertyName, SignalLink link)
81  {
82  if (enable)
83  {
84  link = object->connect(propertyName,
85  SignalSubscriber(
86  AnyFunction::fromDynamicFunction(boost::bind(&ThisProxyType::bounceEvent, this, _1))
87  )).value();
88  }
89  else
90  {
91  bool ok = !object->disconnect(link).hasError();
92  if (!ok)
93  qiLogError("qitype.proxysignal") << "Failed to disconnect from parent signal";
95  }
96  // rebind onSubscribe since link changed
97  SignalBase::setOnSubscribers(boost::bind(&ThisProxyType::onSubscribe, this, _1,
98  object, propertyName, link));
99  return Future<void>{nullptr};
100  }
101 
102  template<typename T, template< class...> class PropertyType>
104  {
105  // Receive notify from backend, trigger on our signal, bypassing our trigger overload
106  SignalType::callSubscribers(args);
107  return AnyReference(typeOf<void>());
108  }
109 
110  template<typename T, template< class...> class PropertyType>
112  GenericObject* object, const std::string& propertyName)
113  {
114  // Just forward to backend, which will notify us in bouceEvent(),
115  // and then we will notify our local Subscribers
116  object->metaPost(propertyName, params);
117  }
118  template<typename T, template< class...> class PropertyType>
119  T ProxyProperty<T, PropertyType>::getter(GenericObject* object, const std::string& propertyName)
120  {
121  return object->property<T>(propertyName).value();
122  }
123  template<typename T, template< class...> class PropertyType>
124  bool ProxyProperty<T, PropertyType>::setter(T& target, const T& v, GenericObject* object, const std::string& propertyName)
125  {
126  // no need to fill target it's never used since we have a getter
127  object->setProperty(propertyName, v).value(); // throw on remote error
128  // Prevent local subscribers from being called
129  return false;
130  }
131 }
132 #endif // _QITYPE_PROXYPROPERTY_HPP_
ProxyProperty(AnyObject object, const std::string &propertyName)
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:545
Future< void > onSubscribe(bool enable, GenericObject *object, const std::string &propertyName, SignalLink link)
static const SignalLink invalidSignalLink
Definition: signal.hpp:151
void setOnSubscribers(OnSubscribers onSubscribers)
AnyReference bounceEvent(const AnyReferenceVector args)
void setTriggerOverride(Trigger trigger)
#define qiLogError(...)
Log in error mode.
Definition: log.hpp:120
void makeProxyProperty(PropertyType< T > &target, AnyObject object, const std::string &signalName)
void setup(AnyObject object, const std::string &propertyName)
std::vector< AnyReference > AnyReferenceVector
void triggerOverride(const GenericFunctionParameters &params, MetaCallType, GenericObject *object, const std::string &propertyName)
MetaCallType
Definition: typeobject.hpp:24
static AnyFunction fromDynamicFunction(DynamicFunction f)
Convenient log macro.
qi::uint64_t SignalLink
Definition: signal.hpp:36
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308