libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
signal.hxx
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 _QITYPE_DETAIL_SIGNAL_HXX_
8 #define _QITYPE_DETAIL_SIGNAL_HXX_
9 
10 #include <qi/trackable.hpp>
12 #include <boost/bind.hpp>
14 
15 namespace qi
16 {
17  template <typename T>
18  template <typename F, typename Arg0, typename... Args>
19  SignalSubscriber SignalF<T>::connect(F&& func, Arg0&& arg0, Args&&... args)
20  {
21  SignalSubscriber s =
22  connect(qi::bind(std::forward<F>(func), std::forward<Arg0>(arg0), std::forward<Args>(args)...));
23  return s;
24  }
25 
26  template<typename T>
27  SignalSubscriber SignalF<T>::connect(AnyFunction f)
28  {
29  auto execContext = executionContext();
30  if (execContext)
31  {
32  return SignalBase::connect(SignalSubscriber(std::move(f), execContext));
33  }
34  else
35  {
36  return SignalBase::connect(SignalSubscriber(std::move(f), MetaCallType_Auto));
37  }
38  }
39  template<typename T>
40  SignalSubscriber SignalF<T>::connect(const SignalSubscriber& sub)
41  {
42  return SignalBase::connect(std::move(sub));
43  }
44 
45  template<typename T>
46  template<class ForcedSignalType, class SignalType>
47  SignalSubscriber SignalF<T>::connectSignal(SignalType& signal)
48  {
49  int curId = 0;
50  SignalLink* trackLink = nullptr;
51  createNewTrackLink(curId, trackLink);
52 
53  boost::weak_ptr<SignalBasePrivate> maybeThisSignalPrivate(this->_p);
54 
55  auto onSignalLost = [=]{
56  if (auto thisSignalPrivate = maybeThisSignalPrivate.lock())
57  {
58  disconnectTrackLink(curId);
59  }
60  };
61 
62  auto forwardSignalCall = qi::trackWithFallback(
63  std::move(onSignalLost),
64  static_cast<ForcedSignalType&>(signal),
65  boost::weak_ptr<SignalBasePrivate>(signal._p));
66 
67  SignalSubscriber s = connect(std::move(forwardSignalCall));
68 
69  *trackLink = s;
70  return s;
71  }
72 
73  template<typename T>
74  template<typename U>
75  SignalSubscriber SignalF<T>::connect(SignalF<U>& signal)
76  {
77  return connectSignal<boost::function<U>>(signal);
78  }
79 
80  template <typename T>
81  template <typename... P>
82  SignalSubscriber SignalF<T>::connect(Signal<P...>& signal)
83  {
84  typedef void(ftype)(P...);
85  return connectSignal<boost::function<ftype>>(signal);
86  }
87 
88  template<typename F>
89  SignalSubscriber SignalBase::connect(boost::function<F> fun)
90  {
91  return connect(AnyFunction::from(std::move(fun)));
92  }
93  // TODO: taking by forward ref is too greedy and connect(SignalSubscriber) takes this overload
94  // find a way to fix this
95  template<typename T>
96  template<typename F>
97  SignalSubscriber SignalF<T>::connect(F c)
98  {
99  SignalSubscriber sub = connect(qi::AnyFunction::from(boost::function<T>(std::move(c))));
101  sub.setCallType(MetaCallType_Direct);
102  return sub;
103  }
104  template<typename T>
105  SignalSubscriber SignalF<T>::connect(const AnyObject& obj, const std::string& slot)
106  {
107  return SignalBase::connect(obj, slot);
108  }
109 
110  template<typename T>
111  SignalSubscriber SignalF<T>::connect(const AnyObject& obj, unsigned int slot)
112  {
113  return connect(SignalSubscriber(obj, slot));
114  }
115 
116  namespace detail
117  {
118 
119  template<typename T> class BounceToSignalBase
120  {
121  // This default should not be instanciated
122  static_assert(sizeof(T) < 0, "You can't instanciate BounceToSignalBase");
123  public:
125  {
126  }
127  };
128  #define pushArg(z, n, _) \
129  args.push_back(AutoAnyReference(p ##n));
130  #define makeBounce(n, argstypedecl, argstype, argsdecl, argsues, comma) \
131  template<typename R comma argstypedecl> \
132  class BounceToSignalBase<R(argstype)> { \
133  public: \
134  BounceToSignalBase(SignalBase& signalBase) : signalBase(signalBase) {} \
135  R operator()(argsdecl) { \
136  AnyReferenceVector args; \
137  BOOST_PP_REPEAT(n, pushArg, _); \
138  signalBase.trigger(args); \
139  } \
140  private: \
141  SignalBase& signalBase; \
142  };
144  #undef makeBounce
145  #undef pushArg
146 
147  } // detail
148 
149  template<typename T>
151  : SignalF(nullptr, std::move(onSubscribers))
152  {
153  }
154 
155  template<typename T>
157  : SignalBase(execContext, onSubscribers)
158  {
159  * (boost::function<T>*)this = detail::BounceToSignalBase<T>(*this);
160  _setSignature(detail::functionArgumentsSignature<T>());
161  }
162 
163 
164  template<typename T>
166  {
167  return detail::functionArgumentsSignature<T>();
168  }
169 } // qi
170 #endif // _QITYPE_DETAIL_SIGNAL_HXX_
auto trackWithFallback(boost::function< void()> onFail, F &&f, T &&toTrack) -> decltype(detail::BindTransform< T >::wrap(std::forward< T >(toTrack), std::forward< F >(f), std::move(onFail)))
Definition: trackable.hxx:413
BounceToSignalBase(SignalBase &sb)
Definition: signal.hxx:124
void _setSignature(const Signature &s)
Honor the default behavior.
Definition: typeobject.hpp:26
virtual qi::Signature signature() const
Definition: signal.hxx:165
boost::function< Future< void >(bool)> OnSubscribers
Definition: signal.hpp:45
Force a synchronous call.
Definition: typeobject.hpp:28
#define makeBounce(n, argstypedecl, argstype, argsdecl, argsues, comma)
Definition: signal.hxx:130
SignalSubscriber connect(boost::function< F > func)
Definition: signal.hxx:89
Object< Empty > AnyObject
Definition: anyobject.hpp:21
static AnyFunction from(F &&func)
qi::uint64_t SignalLink
Definition: signal.hpp:36
SignalSubscriber connect(...)
Definition: signal.hxx:19
SignalF(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hxx:150
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
#define QI_GEN(f)
Definition: preproc.hpp:476