libqi-api  2.4.3.28
 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 
35  typedef qi::uint64_t SignalLink;
36 
37  //Signal are not copyable, they belong to a class.
38  class QI_API SignalBase : boost::noncopyable
39  {
40  public:
41  typedef boost::function<void(bool)> OnSubscribers;
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(const 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  typedef boost::function<void(const GenericFunctionParameters& params, MetaCallType callType)> Trigger;
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 #define QI_SIGNAL_TEMPLATE_DECL typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7
120 #define QI_SIGNAL_TEMPLATE P0,P1,P2,P3,P4,P5,P6,P7
121 
122  template<QI_SIGNAL_TEMPLATE_DECL> class Signal;
123 
124  template<typename T>
125  class SignalF: public SignalBase, public boost::function<T>
126  {
127  public:
133  SignalF(OnSubscribers onSubscribers = OnSubscribers());
134  typedef T FunctionType;
135  virtual qi::Signature signature() const;
136  using boost::function<T>::operator();
137 
138 #ifdef DOXYGEN
139 
158 #else
159  template <typename CALLABLE>
160  SignalSubscriber& connect(CALLABLE c);
163  SignalSubscriber& connect(const boost::function<T>& func);
164  template <typename U>
166  template <QI_SIGNAL_TEMPLATE_DECL>
168 
169 #define genConnect(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma) \
170  template <typename F, typename P comma ATYPEDECL> \
171  SignalSubscriber& connect(const F& func, const P& p comma ADECL);
173 #undef genConnect
174 
175  SignalSubscriber& connect(const AnyObject& obj, unsigned int slot);
176  SignalSubscriber& connect(const AnyObject& obj, const std::string& slot);
177 #endif
178 
179  private:
180  template <typename ARG0>
181  inline typename boost::enable_if<
182  boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
183  SignalSubscriber&>::type
184  _connectMaybeActor(const ARG0& arg0, const boost::function<T>& cb,
185  const boost::function<void()>& fallbackCb);
186  template <typename ARG0>
187  inline typename boost::disable_if<
188  boost::is_base_of<Actor, typename detail::Unwrap<ARG0>::type>,
189  SignalSubscriber&>::type
190  _connectMaybeActor(const ARG0& arg0, const boost::function<T>& cb,
191  const boost::function<void()>& fallbackCb);
192  };
193 
194  namespace detail
195  {
196  template<typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7> struct VoidFunctionType { typedef void(type)(P0, P1, P2, P3, P4, P5, P6, P7); };
197  template<typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6> struct VoidFunctionType<P0, P1, P2, P3, P4, P5, P6, void> { typedef void(type)(P0, P1, P2, P3, P4, P5, P6); };
198  template<typename P0, typename P1, typename P2, typename P3, typename P4, typename P5 > struct VoidFunctionType<P0, P1, P2, P3, P4, P5, void, void> { typedef void(type)(P0, P1, P2, P3, P4, P5); };
199  template<typename P0, typename P1, typename P2, typename P3, typename P4 > struct VoidFunctionType<P0, P1, P2, P3, P4, void, void, void> { typedef void(type)(P0, P1, P2, P3, P4); };
200  template<typename P0, typename P1, typename P2, typename P3 > struct VoidFunctionType<P0, P1, P2, P3, void, void, void, void> { typedef void(type)(P0, P1, P2, P3); };
201  template<typename P0, typename P1, typename P2 > struct VoidFunctionType<P0, P1, P2, void, void, void, void, void> { typedef void(type)(P0, P1, P2); };
202  template<typename P0, typename P1 > struct VoidFunctionType<P0, P1, void, void, void, void, void, void> { typedef void(type)(P0, P1); };
203  template<typename P0 > struct VoidFunctionType<P0, void, void, void, void, void, void, void> { typedef void(type)(P0); };
204  template< > struct VoidFunctionType<void, void, void, void, void, void, void, void> { typedef void(type)(); };
205 
206  }
207 
212  template<
213  typename P0 = void,
214  typename P1 = void,
215  typename P2 = void,
216  typename P3 = void,
217  typename P4 = void,
218  typename P5 = void,
219  typename P6 = void,
220  typename P7 = void
221  >
222  class Signal: public SignalF<typename detail::VoidFunctionType<P0, P1, P2, P3, P4, P5, P6, P7>::type>
223  {
224  public:
225  typedef typename detail::VoidFunctionType<P0, P1, P2, P3, P4, P5, P6, P7>::type FunctionType;
228  Signal(OnSubscribers onSubscribers = OnSubscribers())
229  : ParentType(onSubscribers) {}
230  using boost::function<FunctionType>::operator();
231  };
232 
233 
241  : public boost::enable_shared_from_this<SignalSubscriber>
242  {
243  public:
245  : source(0)
246  , linkId(SignalBase::invalidSignalLink)
247  , target(0)
248  , method(0)
249  , enabled(true)
250  {}
251 
254  SignalSubscriber(const AnyObject& target, unsigned int method);
255 
257 
258  ~SignalSubscriber();
259 
260  void operator = (const SignalSubscriber& b);
261 
269  void call(const GenericFunctionParameters& args, MetaCallType callType);
270 
271  SignalSubscriber& setCallType(MetaCallType ct);
272 
274  void waitForInactive();
275 
276  void addActive(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id());
277  void removeActive(bool acquireLock, boost::thread::id tid = boost::this_thread::get_id());
278  operator SignalLink() const
279  {
280  return linkId;
281  }
285  Signature signature() const;
286  public:
287  // Source information
291 
292  // Target information, kept here to be able to introspect a Subscriber
293  // Mode 1: Direct functor call
296 
297  // Mode 2: metaCall
299  unsigned int method;
300 
301  boost::mutex mutex;
302  // Fields below are protected by lock
303 
304  // If enabled is set to false while lock is acquired,
305  // No more callback will trigger (activeThreads will se no push-back)
306  bool enabled;
307  // Number of calls in progress.
308  // Each entry there is a subscriber call that can no longuer be aborted
309  std::vector<boost::thread::id> activeThreads; // order not preserved
310 
311  boost::condition inactiveThread;
312 
313  // ExecutionContext on which to schedule the call
315  };
316  typedef boost::shared_ptr<SignalSubscriber> SignalSubscriberPtr;
317 }
318 
319 #ifdef _MSC_VER
320 # pragma warning( pop )
321 #endif
322 
323 #include <qi/type/detail/signal.hxx>
324 
326 
327 #endif // _QITYPE_SIGNAL_HPP_
boost::mutex mutex
Definition: signal.hpp:301
Signal(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hpp:228
boost::condition inactiveThread
Definition: signal.hpp:311
#define QI_API
Definition: api.hpp:34
#define genConnect(n, ATYPEDECL, ATYPES, ADECL, AUSE, comma)
Definition: signal.hxx:48
static const SignalLink invalidSignalLink
Definition: signal.hpp:103
boost::shared_ptr< SignalBasePrivate > _p
Definition: signal.hpp:115
Honor the default behavior.
Definition: typeobject.hpp:21
AnyFunction handler
Definition: signal.hpp:294
ExecutionContext * executionContext
Definition: signal.hpp:314
T FunctionType
Definition: signal.hpp:134
AnyWeakObject * target
Definition: signal.hpp:298
SignalSubscriber & connect(...)
Definition: signal.hxx:69
virtual qi::Signature signature() const
Definition: signal.hxx:180
SignalBase * source
Definition: signal.hpp:288
unsigned int method
Definition: signal.hpp:299
boost::function< void(const GenericFunctionParameters &params, MetaCallType callType)> Trigger
Definition: signal.hpp:105
MetaCallType
Definition: typeobject.hpp:19
boost::function< void(bool)> OnSubscribers
Definition: signal.hpp:41
MetaCallType threadingModel
Definition: signal.hpp:295
QI_NO_TYPE(qi::AnyReference)
boost::shared_ptr< SignalSubscriber > SignalSubscriberPtr
Definition: signal.hpp:316
uint64_t uint64_t
Cross-platform unsigned integer of length 64 bits (8 bytes).
Definition: types.hpp:81
qi::uint64_t SignalLink
Definition: signal.hpp:33
std::vector< boost::thread::id > activeThreads
Definition: signal.hpp:309
SignalLink linkId
Uid that can be passed to GenericObject::disconnect()
Definition: signal.hpp:290
detail::VoidFunctionType< P0, P1, P2, P3, P4, P5, P6, P7 >::type FunctionType
Definition: signal.hpp:225
ParentType::OnSubscribers OnSubscribers
Definition: signal.hpp:227
SignalF(OnSubscribers onSubscribers=OnSubscribers())
Definition: signal.hxx:171
SignalF< FunctionType > ParentType
Definition: signal.hpp:226
#define QI_GEN(f)
Definition: preproc.hpp:476