libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
signal.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_SIGNAL_HPP_
8 #define _QI_SIGNAL_HPP_
9 
10 #include <boost/function.hpp>
11 #include <boost/scoped_ptr.hpp>
12 #include <qi/atomic.hpp>
13 #include <qi/macro.hpp>
14 
15 #include <qi/anyfunction.hpp>
16 #include <qi/type/typeobject.hpp>
17 
18 #include <boost/thread/thread.hpp>
19 #include <boost/thread/mutex.hpp>
20 
21 #ifdef _MSC_VER
22 # pragma warning( push )
23 # pragma warning( disable: 4251 )
24 #endif
25 
26 // Macro to be more expressive when emitting a signal. Does nothing, it's normal.
27 #define QI_EMIT
28 
29 namespace qi {
30 
31  class ManageablePrivate;
32  class SignalSubscriber;
33 
34  class SignalBasePrivate;
35 
37 
38 
43  {
44  public:
45  using OnSubscribers = boost::function<Future<void>(bool)>;
46 
47  explicit SignalBase(const Signature &signature, OnSubscribers onSubscribers = OnSubscribers());
48  SignalBase(const Signature &signature, ExecutionContext* execContext,
49  OnSubscribers onSubscribers = OnSubscribers());
50  SignalBase(OnSubscribers onSubscribers = OnSubscribers());
51  SignalBase(ExecutionContext* execContext, OnSubscribers onSubscribers = OnSubscribers());
52 
54  SignalBase(const SignalBase&) = delete;
55  SignalBase& operator=(const SignalBase&) = delete;
56 
57  virtual ~SignalBase();
58 
59  virtual qi::Signature signature() const;
60 
61  template<typename F>
62  SignalSubscriber connect(boost::function<F> func);
63  SignalSubscriber connect(AnyObject object, const unsigned int slot);
64  SignalSubscriber connect(AnyObject object, const std::string& slot);
65 
67  SignalSubscriber connect(const SignalSubscriber& s);
68 
73  Future<SignalSubscriber> connectAsync(const SignalSubscriber&);
74 
80  bool disconnectAll();
86  Future<bool> disconnectAllAsync();
87 
88  QI_API_DEPRECATED_MSG("use disconnectAllAsync instead")
89  bool asyncDisconnectAll()
90  {
91  disconnectAllAsync();
92  return true;
93  }
94 
104  bool disconnect(const SignalLink& link);
105 
113  Future<bool> disconnectAsync(const SignalLink& link);
114 
115  QI_API_DEPRECATED_MSG("use disconnectAsync instead")
116  bool asyncDisconnect(const SignalLink& link)
117  {
118  disconnectAsync(link);
119  return true;
120  }
121 
130  virtual void trigger(const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto);
132  void setCallType(MetaCallType callType);
134  void operator()(
143 
144  std::vector<SignalSubscriber> subscribers();
145  bool hasSubscribers();
146 
149  void setOnSubscribers(OnSubscribers onSubscribers);
150 
152  void _setSignature(const Signature &s);
153  protected:
154  using Trigger = boost::function<void(const GenericFunctionParameters& params, MetaCallType callType)>;
155  void callSubscribers(const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto);
156  void setTriggerOverride(Trigger trigger);
157  void callOnSubscribe(bool v);
158  void createNewTrackLink(int& id, SignalLink*& trackLink);
159  void disconnectTrackLink(int id);
160  ExecutionContext* executionContext() const;
161  void clearExecutionContext();
162 
163  protected:
164  boost::shared_ptr<SignalBasePrivate> _p;
165  friend class SignalBasePrivate;
166  };
167 
168  template <typename... P> class Signal;
169 
170  template<typename T>
171  class SignalF: public SignalBase, public boost::function<T>
172  {
173  public:
179  SignalF(OnSubscribers onSubscribers = OnSubscribers());
180  SignalF(ExecutionContext* execContext, OnSubscribers onSubscribers);
181  using FunctionType = T;
182  virtual qi::Signature signature() const;
183  using boost::function<T>::operator();
184 
185 #ifdef DOXYGEN
186 
209  SignalSubscriber connect(...);
210 #else
211  template <typename F>
212  SignalSubscriber connect(F c);
213  SignalSubscriber connect(AnyFunction func);
214  SignalSubscriber connect(const SignalSubscriber& sub);
215  template <typename U>
216  SignalSubscriber connect(SignalF<U>& signal);
217  template <typename... P>
218  SignalSubscriber connect(Signal<P...>& signal);
219 
220  template <typename F, typename Arg0, typename... Args>
221  SignalSubscriber connect(F&& func, Arg0&& arg0, Args&&... args);
222 
223  SignalSubscriber connect(const AnyObject& obj, unsigned int slot);
224  SignalSubscriber connect(const AnyObject& obj, const std::string& slot);
225 #endif
226 
227  private:
228  template< class ForcedSignalType, class SignalType >
229  SignalSubscriber connectSignal(SignalType& signal);
230  };
231 
236  template<typename... P>
237  class Signal: public SignalF<void(P...)>
238  {
239  public:
240  typedef void(FunctionType)(P...); // FIXME: VS2013 fails if this is replaced by `using`
243  Signal(OnSubscribers onSubscribers = OnSubscribers())
244  : ParentType(onSubscribers) {}
245  explicit Signal(ExecutionContext* execContext, OnSubscribers onSubscribers = OnSubscribers())
246  : ParentType(execContext, onSubscribers) {}
247  using boost::function<FunctionType>::operator();
248  };
249 
250  template <>
251  class Signal<void> : public Signal<>
252  {};
253 
255 
263 QI_WARNING_PUSH()
264 QI_WARNING_DISABLE(4996, deprecated-declarations) // ignore linkId deprecation warnings
265  class QI_API SignalSubscriber
266  {
267 QI_WARNING_POP()
268  public:
269  friend class FunctorCall;
270  friend class ManageablePrivate;
271  friend class SignalBase;
272  friend class SignalBasePrivate;
273 
274  SignalSubscriber();
275 
276  SignalSubscriber(AnyFunction func, MetaCallType callType = MetaCallType_Auto);
277  SignalSubscriber(AnyFunction func, ExecutionContext* ec);
278  SignalSubscriber(const AnyObject& target, unsigned int method);
279 
280  // This is copiable but not movable (never invalid).
281  SignalSubscriber(const SignalSubscriber& other);
282  SignalSubscriber& operator=(const SignalSubscriber& other);
283 
284  ~SignalSubscriber();
285 
293  void call(const GenericFunctionParameters& args, MetaCallType callType);
294 
295  void call(const std::shared_ptr<GenericFunctionParameters>& args,
296  MetaCallType callType);
297 
298  SignalSubscriber setCallType(MetaCallType ct);
299 
301  SignalLink link() const;
302  operator SignalLink() const;
303 
307  Signature signature() const;
308 
309  private:
310  std::shared_ptr<SignalSubscriberPrivate> _p;
311 
312  void callImpl(const GenericFunctionParameters& args);
313 
314  boost::optional<ExecutionContext*> executionContextFor(MetaCallType callType) const;
315 
316  // Call the subscriber with the given arguments, which can be passed by
317  // value or by pointer (any `Readable` will do).
318  //
319  // (GenericFunctionParameters || Readable<GenericFunctionParameters>) Args
320  template<typename Args>
321  void callWithValueOrPtr(const Args& args, MetaCallType callType);
322 
323  public:
324  QI_API_DEPRECATED_MSG("please use link() instead or cast to qi::SignalLink")
325  SignalLink linkId;
326  };
327 
328  using SignalSubscriberPtr = boost::shared_ptr<SignalSubscriber>;
329 
331  {
334 
335  // Non-copyable
338 
339  // Source information
340  boost::weak_ptr<SignalBasePrivate> source;
343 
344  // Target information, kept here to be able to introspect a Subscriber
345  // Mode 1: Direct functor call
348 
349  // Mode 2: metaCall
350  boost::scoped_ptr<AnyWeakObject> target;
351  unsigned int method = 0;
352 
353  // If enabled is set to false, no more callback will trigger
354  std::atomic<bool> enabled{true};
355 
356  // ExecutionContext on which to schedule the call
357  std::atomic<ExecutionContext*> executionContext{nullptr};
358  };
359 } // qi
360 
361 #ifdef _MSC_VER
362 # pragma warning( pop )
363 #endif
364 
365 #include <qi/type/detail/signal.hxx>
366 
368 
369 #endif // _QITYPE_SIGNAL_HPP_
boost::scoped_ptr< AnyWeakObject > target
Definition: signal.hpp:350
#define QI_API
Definition: api.hpp:33
SignalLink linkId
Uid that can be passed to GenericObject::disconnect()
Definition: signal.hpp:342
std::atomic< ExecutionContext * > executionContext
Definition: signal.hpp:357
boost::shared_ptr< SignalSubscriber > SignalSubscriberPtr
Definition: signal.hpp:328
static const SignalLink invalidSignalLink
Definition: signal.hpp:151
boost::shared_ptr< SignalBasePrivate > _p
Definition: signal.hpp:164
Honor the default behavior.
Definition: typeobject.hpp:26
Signal(ExecutionContext *execContext, OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hpp:245
std::atomic< bool > enabled
Definition: signal.hpp:354
virtual qi::Signature signature() const
Definition: signal.hxx:165
void(const AnyValue &) FunctionType
Definition: signal.hpp:181
boost::function< Future< void >(bool)> OnSubscribers
Definition: signal.hpp:45
Force a synchronous call.
Definition: typeobject.hpp:28
#define QI_API_DEPRECATED_MSG(msg__)
Compiler flags to mark a function as deprecated. It will generate a compiler warning.
Definition: macro.hpp:55
MetaCallType threadingModel
Definition: signal.hpp:347
Various macros for qi. (deprecated, export API, disallow copy, ..) <includename>qi/macro.hpp</includename> .
boost::weak_ptr< SignalBasePrivate > source
Definition: signal.hpp:340
MetaCallType
Definition: typeobject.hpp:24
SignalSubscriberPrivate & operator=(const SignalSubscriberPrivate &)=delete
typename ParentType::OnSubscribers OnSubscribers
Definition: signal.hpp:242
Signal(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hpp:243
QI_WARNING_DISABLE(4996, deprecated-declarations) class SignalSubscriber
Definition: signal.hpp:264
boost::function< void(const GenericFunctionParameters &params, MetaCallType callType)> Trigger
Definition: signal.hpp:154
qi::uint64_t SignalLink
Definition: signal.hpp:36
SignalSubscriber connect(...)
Definition: signal.hxx:19
SignalF(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hxx:150
uint64_t uint64_t
Definition: types.hpp:66
#define QI_NO_TYPE(T)