libqi-api  release-2.5.3-2016-11-18
 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 <qi/atomic.hpp>
11 
12 #include <qi/anyfunction.hpp>
13 #include <qi/type/typeobject.hpp>
14 
15 #include <boost/thread/thread.hpp>
16 #include <boost/thread/mutex.hpp>
17 #include <boost/thread/condition.hpp>
18 #include <boost/enable_shared_from_this.hpp>
19 
20 #ifdef _MSC_VER
21 # pragma warning( push )
22 # pragma warning( disable: 4251 )
23 #endif
24 
25 // Macro to be more expressive when emitting a signal. Does nothing, it's normal.
26 #define QI_EMIT
27 
28 namespace qi {
29 
30  class ManageablePrivate;
31  class SignalSubscriber;
32 
33  class SignalBasePrivate;
34 
36 
37  //Signal are not copyable, they belong to a class.
38  class QI_API SignalBase : boost::noncopyable
39  {
40  public:
41  using OnSubscribers = boost::function<void(bool)>;
42  explicit SignalBase(const Signature &signature, OnSubscribers onSubscribers = OnSubscribers());
43  SignalBase(OnSubscribers onSubscribers=OnSubscribers());
44  virtual ~SignalBase();
45  virtual qi::Signature signature() const;
46  template<typename F>
47  SignalSubscriber& connect(boost::function<F> func);
48  SignalSubscriber& connect(const SignalSubscriber& s);
49  SignalSubscriber& connect(AnyObject object, const unsigned int slot);
50  SignalSubscriber& connect(AnyObject object, const std::string& slot);
51 
56  bool disconnectAll();
61  bool asyncDisconnectAll();
62 
71  bool disconnect(const SignalLink& link);
72 
77  bool asyncDisconnect(const SignalLink& link);
78 
87  virtual void trigger(const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto);
89  void setCallType(MetaCallType callType);
91  void operator()(
100 
101  std::vector<SignalSubscriber> subscribers();
102  bool hasSubscribers();
104  protected:
105  using Trigger = boost::function<void(const GenericFunctionParameters& params, MetaCallType callType)>;
106  void callSubscribers(const GenericFunctionParameters& params, MetaCallType callType = MetaCallType_Auto);
107  void setTriggerOverride(Trigger trigger);
108  void setOnSubscribers(OnSubscribers onSubscribers);
109  void callOnSubscribe(bool v);
110  void createNewTrackLink(int& id, SignalLink*& trackLink);
111  void disconnectTrackLink(int id);
112  public:
113  void _setSignature(const Signature &s);
114  // C4251
115  boost::shared_ptr<SignalBasePrivate> _p;
116  friend class SignalBasePrivate;
117  };
118 
119  template <typename... P> class Signal;
120 
121  template<typename T>
122  class SignalF: public SignalBase, public boost::function<T>
123  {
124  public:
130  SignalF(OnSubscribers onSubscribers = OnSubscribers());
131  using FunctionType = T;
132  virtual qi::Signature signature() const;
133  using boost::function<T>::operator();
134 
135 #ifdef DOXYGEN
136 
155 #else
156  template <typename F>
160  template <typename U>
162  template <typename... P>
164 
165  template <typename F, typename Arg0, typename... Args>
166  SignalSubscriber& connect(F&& func, Arg0&& arg0, Args&&... args);
167 
168  SignalSubscriber& connect(const AnyObject& obj, unsigned int slot);
169  SignalSubscriber& connect(const AnyObject& obj, const std::string& slot);
170 #endif
171  };
172 
177  template<typename... P>
178  class Signal: public SignalF<void(P...)>
179  {
180  public:
181  typedef void(FunctionType)(P...); // FIXME: VS2013 fails if this is replaced by `using`
184  Signal(OnSubscribers onSubscribers = OnSubscribers())
185  : ParentType(onSubscribers) {}
186  using boost::function<FunctionType>::operator();
187  };
188 
189  template <>
190  class Signal<void> : public Signal<>
191  {};
192 
200  : public boost::enable_shared_from_this<SignalSubscriber>
201  {
202  public:
204 
207  SignalSubscriber(const AnyObject& target, unsigned int method);
208 
210 
211  ~SignalSubscriber();
212 
213  void operator = (const SignalSubscriber& b);
214 
222  void call(const GenericFunctionParameters& args, MetaCallType callType);
223 
224  SignalSubscriber& setCallType(MetaCallType ct);
225 
227  void waitForInactive();
228 
229  void addActive(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id());
230  void removeActive(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id());
231  operator SignalLink() const
232  {
233  return linkId;
234  }
238  Signature signature() const;
239  public:
240  // Source information
244 
245  // Target information, kept here to be able to introspect a Subscriber
246  // Mode 1: Direct functor call
249 
250  // Mode 2: metaCall
251  boost::scoped_ptr<AnyWeakObject> target;
252  unsigned int method;
253 
254  boost::mutex mutex;
255  // Fields below are protected by lock
256 
257  // If enabled is set to false while lock is acquired,
258  // No more callback will trigger (activeThreads will se no push-back)
259  bool enabled;
260  // Number of calls in progress.
261  // Each entry there is a subscriber call that can no longuer be aborted
262  std::vector<boost::thread::id> activeThreads; // order not preserved
263 
264  boost::condition inactiveThread;
265 
266  // ExecutionContext on which to schedule the call
268  };
269  using SignalSubscriberPtr = boost::shared_ptr<SignalSubscriber>;
270 }
271 
272 #ifdef _MSC_VER
273 # pragma warning( pop )
274 #endif
275 
276 #include <qi/type/detail/signal.hxx>
277 
279 
280 #endif // _QITYPE_SIGNAL_HPP_
boost::mutex mutex
Definition: signal.hpp:254
boost::function< void(bool)> OnSubscribers
Definition: signal.hpp:41
boost::condition inactiveThread
Definition: signal.hpp:264
#define QI_API
Definition: api.hpp:33
boost::shared_ptr< SignalSubscriber > SignalSubscriberPtr
Definition: signal.hpp:269
static const SignalLink invalidSignalLink
Definition: signal.hpp:103
boost::shared_ptr< SignalBasePrivate > _p
Definition: signal.hpp:115
Honor the default behavior.
Definition: typeobject.hpp:23
AnyFunction handler
Definition: signal.hpp:247
ExecutionContext * executionContext
Definition: signal.hpp:267
SignalSubscriber & connect(...)
Definition: signal.hxx:19
virtual qi::Signature signature() const
Definition: signal.hxx:142
void(const AnyValue &) FunctionType
Definition: signal.hpp:131
SignalBase * source
Definition: signal.hpp:241
unsigned int method
Definition: signal.hpp:252
boost::scoped_ptr< AnyWeakObject > target
Definition: signal.hpp:251
MetaCallType
Definition: typeobject.hpp:21
MetaCallType threadingModel
Definition: signal.hpp:248
typename ParentType::OnSubscribers OnSubscribers
Definition: signal.hpp:183
Signal(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hpp:184
boost::function< void(const GenericFunctionParameters &params, MetaCallType callType)> Trigger
Definition: signal.hpp:105
qi::uint64_t SignalLink
Definition: signal.hpp:35
std::vector< boost::thread::id > activeThreads
Definition: signal.hpp:262
SignalLink linkId
Uid that can be passed to GenericObject::disconnect()
Definition: signal.hpp:243
SignalF(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hxx:133
uint64_t uint64_t
Definition: types.hpp:66
#define QI_NO_TYPE(T)