libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proxysignal.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_PROXYSIGNAL_HPP_
8 #define _QI_TYPE_PROXYSIGNAL_HPP_
9 
10 #include <boost/bind.hpp>
11 #include <qi/signal.hpp>
12 #include <qi/anyfunction.hpp>
13 #include <qi/anyobject.hpp>
14 
15 namespace qi
16 {
17 
19  template<typename T>
20  class ProxySignal: public SignalF<T>
21  {
22  public:
24  ProxySignal(AnyObject object, const std::string& signalName)
25  : SignalType()
26  {
27  setup(object, signalName);
28  }
30  ~ProxySignal();
31  void setup(AnyObject object, const std::string& signalName)
32  {
34  object.asGenericObject(), signalName, SignalBase::invalidSignalLink));
36  object.asGenericObject(), signalName));
37  }
38  Future<void> onSubscribe(bool enable, GenericObject* object, std::string signalName, SignalLink link);
40  void triggerOverride(const GenericFunctionParameters& params,
41  MetaCallType callType, GenericObject* object, std::string signalName);
42  };
43 
44  template<typename T>
45  void makeProxySignal(SignalF<T>& target, AnyObject object, const std::string& signalName)
46  {
47  ProxySignal<T>& proxy = static_cast<ProxySignal<T> &>(target);
48  proxy.setup(object, signalName);
49  }
50 
51  template<typename T>
52  void makeProxySignal(ProxySignal<T>& target, AnyObject object, const std::string& signalName)
53  {
54  target.setup(object, signalName);
55  }
56 
57  template<typename T>
59  {
60  SignalType::disconnectAll(); // will invoke onsubscribe
61  }
62 
63  template<typename T>
64  qi::Future<void> ProxySignal<T>::onSubscribe(bool enable, GenericObject* object, std::string signalName,
65  SignalLink link)
66  {
67  Future<SignalLink> connectingOrDisconnecting = [=]
68  {
69  if (enable)
70  {
71  return object->connect(
72  signalName, SignalSubscriber(
74  boost::bind(&ProxySignal<T>::bounceEvent, this, _1)))).async();
75  }
76  else
77  {
78  return object->disconnect(link).async().then([](Future<void> f)
79  {
80  bool ok = !f.hasError();
81  if (!ok)
82  qiLogError("qitype.proxysignal") << "Failed to disconnect from parent signal";
84  });
85  }
86  }();
87 
88  boost::weak_ptr<SignalBasePrivate> weakP = this->_p;
89  return connectingOrDisconnecting.andThen([=](SignalLink link)
90  { // link changed, rebind ourselve if we're still alive
91  if (auto p = weakP.lock())
92  {
93  this->setOnSubscribers([=](bool enable) // TODO: remove `this->` after upgrading from GCC4.8
94  // Currently necessary because of a bug in g++4.8
95  {
96  return onSubscribe(enable, object, signalName, link);
97  });
98  }
99  });
100  }
101 
102  template<typename T>
104  {
105  // Trigger on our signal, bypassing our trigger overload
106  SignalType::callSubscribers(args);
107  return AnyReference(typeOf<void>());
108  }
109 
110  template<typename T>
112  GenericObject* object, std::string signalName)
113  {
114  // Just forward to backend, which will notify us in bouceEvent(),
115  // and then we will notify our local Subscribers
116  object->metaPost(signalName, params);
117  }
118 
119 }
120 
121 
122 
123 #endif // _QITYPE_PROXYSIGNAL_HPP_
void connect(const AF &fun, FutureCallbackType type=FutureCallbackType_Auto)
Definition: future_fwd.hpp:545
static const SignalLink invalidSignalLink
Definition: signal.hpp:151
void setOnSubscribers(OnSubscribers onSubscribers)
Future< void > onSubscribe(bool enable, GenericObject *object, std::string signalName, SignalLink link)
Definition: proxysignal.hpp:64
ProxySignal(AnyObject object, const std::string &signalName)
Definition: proxysignal.hpp:24
void setTriggerOverride(Trigger trigger)
#define qiLogError(...)
Log in error mode.
Definition: log.hpp:120
Signal proxy, using an AnyObject and signal id as backend.
Definition: proxysignal.hpp:20
std::vector< AnyReference > AnyReferenceVector
MetaCallType
Definition: typeobject.hpp:24
auto andThen(FutureCallbackType type, F &&func) -> Future< typename std::decay< typename std::result_of< F(ValueType)>::type >::type >
Same as then(), but the callback is called only if this future finishes with a value.
Definition: future_fwd.hpp:506
static AnyFunction fromDynamicFunction(DynamicFunction f)
AnyReference bounceEvent(const AnyReferenceVector args)
void makeProxySignal(SignalF< T > &target, AnyObject object, const std::string &signalName)
Definition: proxysignal.hpp:45
qi::uint64_t SignalLink
Definition: signal.hpp:36
void setup(AnyObject object, const std::string &signalName)
Definition: proxysignal.hpp:31
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
void triggerOverride(const GenericFunctionParameters &params, MetaCallType callType, GenericObject *object, std::string signalName)
bool hasError(int msecs=FutureTimeout_Infinite) const
Definition: future_fwd.hpp:348