Event.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 #ifndef GAZEBO_COMMON_EVENT_HH_
18 #define GAZEBO_COMMON_EVENT_HH_
19 
20 #include <atomic>
21 #include <functional>
22 #include <list>
23 #include <map>
24 #include <memory>
25 #include <mutex>
26 
27 #include "gazebo/gazebo_config.h"
28 #include "gazebo/common/Time.hh"
30 #include "gazebo/util/system.hh"
31 
32 #include "ignition/common/Profiler.hh"
33 
34 namespace gazebo
35 {
38  namespace event
39  {
42 
45  class GZ_COMMON_VISIBLE Event
46  {
48  public: Event();
49 
51  public: virtual ~Event();
52 
55  public: virtual void Disconnect(int _id) = 0;
56 
59  public: bool Signaled() const;
60 
63  public: void SetSignaled(const bool _sig);
64 
66  private: bool signaled;
67  };
68 
70  class GZ_COMMON_VISIBLE Connection
71  {
75  public: Connection(Event *_e, const int _i);
76 
78  public: ~Connection();
79 
82  public: int Id() const;
83 
85  private: Event *event = nullptr;
86 
88  private: int id = -1;
89 
91  private: common::Time creationTime;
92 
94  public: template<typename T> friend class EventT;
95  };
96 
98  template<typename T>
99  class EventT : public Event
100  {
102  public: EventT();
103 
105  public: virtual ~EventT();
106 
111  public: ConnectionPtr Connect(const std::function<T> &_subscriber);
112 
115  public: virtual void Disconnect(int _id);
116 
119  public: unsigned int ConnectionCount() const;
120 
122  public: void operator()()
123  {this->Signal();}
124 
127  public: template< typename P >
128  void operator()(const P &_p)
129  {
130  this->Signal(_p);
131  }
132 
136  public: template< typename P1, typename P2 >
137  void operator()(const P1 &_p1, const P2 &_p2)
138  {
139  this->Signal(_p1, _p2);
140  }
141 
146  public: template< typename P1, typename P2, typename P3 >
147  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
148  {
149  this->Signal(_p1, _p2, _p3);
150  }
151 
157  public: template< typename P1, typename P2, typename P3, typename P4 >
158  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
159  const P4 &_p4)
160  {
161  this->Signal(_p1, _p2, _p3, _p4);
162  }
163 
170  public: template< typename P1, typename P2, typename P3, typename P4,
171  typename P5 >
172  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
173  const P4 &_p4, const P5 &_p5)
174  {
175  this->Signal(_p1, _p2, _p3, _p4, _p5);
176  }
177 
185  public: template< typename P1, typename P2, typename P3, typename P4,
186  typename P5, typename P6 >
187  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
188  const P4 &_p4, const P5 &_p5, const P6 &_p6)
189  {
190  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6);
191  }
192 
201  public: template< typename P1, typename P2, typename P3, typename P4,
202  typename P5, typename P6, typename P7 >
203  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
204  const P4 &_p4, const P5 &_p5, const P6 &_p6,
205  const P7 &_p7)
206  {
207  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
208  }
209 
219  public: template< typename P1, typename P2, typename P3, typename P4,
220  typename P5, typename P6, typename P7, typename P8 >
221  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
222  const P4 &_p4, const P5 &_p5, const P6 &_p6,
223  const P7 &_p7, const P8 &_p8)
224  {
225  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
226  }
227 
238  public: template< typename P1, typename P2, typename P3, typename P4,
239  typename P5, typename P6, typename P7, typename P8,
240  typename P9 >
241  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
242  const P4 &_p4, const P5 &_p5, const P6 &_p6,
243  const P7 &_p7, const P8 &_p8, const P9 &_p9)
244  {
245  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
246  }
247 
259  public: template< typename P1, typename P2, typename P3, typename P4,
260  typename P5, typename P6, typename P7, typename P8,
261  typename P9, typename P10 >
262  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
263  const P4 &_p4, const P5 &_p5, const P6 &_p6,
264  const P7 &_p7, const P8 &_p8, const P9 &_p9,
265  const P10 &_p10)
266  {
267  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
268  }
269 
271  public: void Signal()
272  {
273  IGN_PROFILE("Event::Signal");
274 
275  this->Cleanup();
276 
277  this->SetSignaled(true);
278  for (const auto &iter: this->connections)
279  {
280  if (iter.second->on)
281  {
282  IGN_PROFILE_BEGIN("callback0");
283  iter.second->callback();
284  IGN_PROFILE_END();
285  }
286  }
287  }
288 
291  public: template< typename P >
292  void Signal(const P &_p)
293  {
294  IGN_PROFILE("Event::Signal");
295 
296  this->Cleanup();
297 
298  this->SetSignaled(true);
299  for (const auto &iter: this->connections)
300  {
301  if (iter.second->on)
302  {
303  IGN_PROFILE_BEGIN("callback1");
304  iter.second->callback(_p);
305  IGN_PROFILE_END();
306  }
307  }
308  }
309 
313  public: template< typename P1, typename P2 >
314  void Signal(const P1 &_p1, const P2 &_p2)
315  {
316  IGN_PROFILE("Event::Signal");
317 
318  this->Cleanup();
319 
320  this->SetSignaled(true);
321  for (const auto &iter: this->connections)
322  {
323  if (iter.second->on)
324  {
325  IGN_PROFILE_BEGIN("callback2");
326  iter.second->callback(_p1, _p2);
327  IGN_PROFILE_END();
328  }
329  }
330  }
331 
336  public: template< typename P1, typename P2, typename P3 >
337  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
338  {
339  IGN_PROFILE("Event::Signal");
340 
341  this->Cleanup();
342 
343  this->SetSignaled(true);
344  for (const auto &iter: this->connections)
345  {
346  if (iter.second->on)
347  {
348  IGN_PROFILE_BEGIN("callback3");
349  iter.second->callback(_p1, _p2, _p3);
350  IGN_PROFILE_END();
351  }
352  }
353  }
354 
360  public: template<typename P1, typename P2, typename P3, typename P4>
361  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
362  const P4 &_p4)
363  {
364  IGN_PROFILE("Event::Signal");
365 
366  this->Cleanup();
367 
368  this->SetSignaled(true);
369  for (const auto &iter: this->connections)
370  {
371  if (iter.second->on)
372  {
373  IGN_PROFILE_BEGIN("callback4");
374  iter.second->callback(_p1, _p2, _p3, _p4);
375  IGN_PROFILE_END();
376  }
377  }
378  }
379 
386  public: template<typename P1, typename P2, typename P3, typename P4,
387  typename P5>
388  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
389  const P4 &_p4, const P5 &_p5)
390  {
391  IGN_PROFILE("Event::Signal");
392 
393  this->Cleanup();
394 
395  this->SetSignaled(true);
396  for (const auto &iter: this->connections)
397  {
398  if (iter.second->on)
399  {
400  IGN_PROFILE_BEGIN("callback5");
401  iter.second->callback(_p1, _p2, _p3, _p4, _p5);
402  IGN_PROFILE_END();
403  }
404  }
405  }
406 
414  public: template<typename P1, typename P2, typename P3, typename P4,
415  typename P5, typename P6>
416  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
417  const P4 &_p4, const P5 &_p5, const P6 &_p6)
418  {
419  IGN_PROFILE("Event::Signal");
420 
421  this->Cleanup();
422 
423  this->SetSignaled(true);
424  for (const auto &iter: this->connections)
425  {
426  if (iter.second->on)
427  {
428  IGN_PROFILE_BEGIN("callback6");
429  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6);
430  IGN_PROFILE_END();
431  }
432  }
433  }
434 
443  public: template<typename P1, typename P2, typename P3, typename P4,
444  typename P5, typename P6, typename P7>
445  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
446  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7)
447  {
448  IGN_PROFILE("Event::Signal");
449 
450  this->Cleanup();
451 
452  this->SetSignaled(true);
453  for (const auto &iter: this->connections)
454  {
455  if (iter.second->on)
456  {
457  IGN_PROFILE_BEGIN("callback7");
458  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
459  IGN_PROFILE_END();
460  }
461  }
462  }
463 
473  public: template<typename P1, typename P2, typename P3, typename P4,
474  typename P5, typename P6, typename P7, typename P8>
475  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
476  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
477  const P8 &_p8)
478  {
479  IGN_PROFILE("Event::Signal");
480 
481  this->Cleanup();
482 
483  this->SetSignaled(true);
484  for (const auto &iter: this->connections)
485  {
486  if (iter.second->on)
487  {
488  IGN_PROFILE_BEGIN("callback8");
489  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
490  IGN_PROFILE_END();
491  }
492  }
493  }
494 
505  public: template< typename P1, typename P2, typename P3, typename P4,
506  typename P5, typename P6, typename P7, typename P8,
507  typename P9 >
508  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
509  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
510  const P8 &_p8, const P9 &_p9)
511  {
512  IGN_PROFILE("Event::Signal");
513 
514  this->Cleanup();
515 
516  this->SetSignaled(true);
517  for (const auto &iter: this->connections)
518  {
519  if (iter.second->on)
520  {
521  IGN_PROFILE_BEGIN("callback9");
522  iter.second->callback(
523  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
524  IGN_PROFILE_END();
525  }
526  }
527  }
528 
540  public: template< typename P1, typename P2, typename P3, typename P4,
541  typename P5, typename P6, typename P7, typename P8,
542  typename P9, typename P10 >
543  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
544  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
545  const P8 &_p8, const P9 &_p9, const P10 &_p10)
546  {
547  this->Cleanup();
548 
549  this->SetSignaled(true);
550  for (const auto &iter: this->connections)
551  {
552  IGN_PROFILE("Event::Signal");
553 
554  if (iter.second->on)
555  {
556  IGN_PROFILE_BEGIN("callback10");
557  iter.second->callback(
558  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
559  IGN_PROFILE_END();
560  }
561  }
562  }
563 
567  private: void Cleanup();
568 
570  private: class EventConnection
571  {
573  public: EventConnection(const bool _on, const std::function<T> &_cb)
574  : callback(_cb)
575  {
576  // Windows Visual Studio 2012 does not have atomic_bool constructor,
577  // so we have to set "on" using operator=
578  this->on = _on;
579  }
580 
582  public: std::atomic_bool on;
583 
585  public: std::function<T> callback;
586  };
587 
590  typedef std::map<int, std::unique_ptr<EventConnection>> EvtConnectionMap;
591 
593  private: EvtConnectionMap connections;
594 
596  private: std::mutex mutex;
597 
599  private: std::list<typename EvtConnectionMap::const_iterator>
600  connectionsToRemove;
601  };
602 
604  template<typename T>
606  : Event()
607  {
608  }
609 
611  template<typename T>
613  {
614  this->connections.clear();
615  }
616 
619  template<typename T>
620  ConnectionPtr EventT<T>::Connect(const std::function<T> &_subscriber)
621  {
622  int index = 0;
623  if (!this->connections.empty())
624  {
625  auto const &iter = this->connections.rbegin();
626  index = iter->first + 1;
627  }
628  this->connections[index].reset(new EventConnection(true, _subscriber));
629  return ConnectionPtr(new Connection(this, index));
630  }
631 
634  template<typename T>
635  unsigned int EventT<T>::ConnectionCount() const
636  {
637  return this->connections.size();
638  }
639 
642  template<typename T>
643  void EventT<T>::Disconnect(int _id)
644  {
645  // Find the connection
646  auto const &it = this->connections.find(_id);
647 
648  if (it != this->connections.end())
649  {
650  it->second->on = false;
651  this->connectionsToRemove.push_back(it);
652  }
653  }
654 
656  template<typename T>
657  void EventT<T>::Cleanup()
658  {
659  std::lock_guard<std::mutex> lock(this->mutex);
660  // Remove all queue connections.
661  for (auto &conn : this->connectionsToRemove)
662  this->connections.erase(conn);
663  this->connectionsToRemove.clear();
664  }
666  }
667 }
668 #endif
A Time class, can be used to hold wall- or sim-time.
Definition: Time.hh:48
A class that encapsulates a connection.
Definition: Event.hh:71
int Id() const
Get the id of this connection.
Connection(Event *_e, const int _i)
Constructor.
A class for event processing.
Definition: Event.hh:100
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameter.
Definition: Event.hh:361
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameter.
Definition: Event.hh:337
void operator()(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:128
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameters.
Definition: Event.hh:147
void Signal(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:292
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7)
Signal the event with seven parameters.
Definition: Event.hh:203
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8, const P9 &_p9, const P10 &_p10)
Signal the event with ten parameter.
Definition: Event.hh:543
void operator()()
Access the signal.
Definition: Event.hh:122
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6)
Signal the event with six parameters.
Definition: Event.hh:187
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7)
Signal the event with seven parameter.
Definition: Event.hh:445
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5)
Signal the event with five parameters.
Definition: Event.hh:172
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8, const P9 &_p9, const P10 &_p10)
Signal the event with ten parameters.
Definition: Event.hh:262
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6)
Signal the event with six parameter.
Definition: Event.hh:416
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8, const P9 &_p9)
Signal the event with nine parameter.
Definition: Event.hh:508
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8)
Signal the event with eight parameter.
Definition: Event.hh:475
void Signal(const P1 &_p1, const P2 &_p2)
Signal the event with two parameter.
Definition: Event.hh:314
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8, const P9 &_p9)
Signal the event with nine parameters.
Definition: Event.hh:241
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7, const P8 &_p8)
Signal the event with eight parameters.
Definition: Event.hh:221
void operator()(const P1 &_p1, const P2 &_p2)
Signal the event with two parameters.
Definition: Event.hh:137
void Signal()
Signal the event for all subscribers.
Definition: Event.hh:271
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameters.
Definition: Event.hh:158
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4, const P5 &_p5)
Signal the event with five parameter.
Definition: Event.hh:388
Base class for all events.
Definition: Event.hh:46
Event()
Constructor.
virtual void Disconnect(int _id)=0
Disconnect.
virtual ~Event()
Destructor.
void SetSignaled(const bool _sig)
Set whether this event has been signaled.
bool Signaled() const
Get whether this event has been signaled.
unsigned int ConnectionCount() const
Get the number of connections.
Definition: Event.hh:635
EventT()
Constructor.
Definition: Event.hh:605
virtual void Disconnect(int _id)
Disconnect a callback to this event.
Definition: Event.hh:643
ConnectionPtr Connect(const std::function< T > &_subscriber)
Connect a callback to this event.
Definition: Event.hh:620
virtual ~EventT()
Destructor.
Definition: Event.hh:612
boost::shared_ptr< Connection > ConnectionPtr
Definition: CommonTypes.hh:134
Forward declarations for the common classes.
Definition: Animation.hh:27