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 namespace gazebo
33 {
36  namespace event
37  {
40 
43  class GZ_COMMON_VISIBLE Event
44  {
46  public: Event();
47 
49  public: virtual ~Event();
50 
53  public: virtual void Disconnect(int _id) = 0;
54 
57  public: bool Signaled() const;
58 
61  public: void SetSignaled(const bool _sig);
62 
64  private: bool signaled;
65  };
66 
68  class GZ_COMMON_VISIBLE Connection
69  {
73  public: Connection(Event *_e, const int _i);
74 
76  public: ~Connection();
77 
80  public: int Id() const;
81 
83  private: Event *event = nullptr;
84 
86  private: int id = -1;
87 
89  private: common::Time creationTime;
90 
92  public: template<typename T> friend class EventT;
93  };
94 
96  template<typename T>
97  class EventT : public Event
98  {
100  public: EventT();
101 
103  public: virtual ~EventT();
104 
109  public: ConnectionPtr Connect(const std::function<T> &_subscriber);
110 
113  public: virtual void Disconnect(int _id);
114 
117  public: unsigned int ConnectionCount() const;
118 
120  public: void operator()()
121  {this->Signal();}
122 
125  public: template< typename P >
126  void operator()(const P &_p)
127  {
128  this->Signal(_p);
129  }
130 
134  public: template< typename P1, typename P2 >
135  void operator()(const P1 &_p1, const P2 &_p2)
136  {
137  this->Signal(_p1, _p2);
138  }
139 
144  public: template< typename P1, typename P2, typename P3 >
145  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
146  {
147  this->Signal(_p1, _p2, _p3);
148  }
149 
155  public: template< typename P1, typename P2, typename P3, typename P4 >
156  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
157  const P4 &_p4)
158  {
159  this->Signal(_p1, _p2, _p3, _p4);
160  }
161 
168  public: template< typename P1, typename P2, typename P3, typename P4,
169  typename P5 >
170  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
171  const P4 &_p4, const P5 &_p5)
172  {
173  this->Signal(_p1, _p2, _p3, _p4, _p5);
174  }
175 
183  public: template< typename P1, typename P2, typename P3, typename P4,
184  typename P5, typename P6 >
185  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
186  const P4 &_p4, const P5 &_p5, const P6 &_p6)
187  {
188  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6);
189  }
190 
199  public: template< typename P1, typename P2, typename P3, typename P4,
200  typename P5, typename P6, typename P7 >
201  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
202  const P4 &_p4, const P5 &_p5, const P6 &_p6,
203  const P7 &_p7)
204  {
205  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
206  }
207 
217  public: template< typename P1, typename P2, typename P3, typename P4,
218  typename P5, typename P6, typename P7, typename P8 >
219  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
220  const P4 &_p4, const P5 &_p5, const P6 &_p6,
221  const P7 &_p7, const P8 &_p8)
222  {
223  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
224  }
225 
236  public: template< typename P1, typename P2, typename P3, typename P4,
237  typename P5, typename P6, typename P7, typename P8,
238  typename P9 >
239  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
240  const P4 &_p4, const P5 &_p5, const P6 &_p6,
241  const P7 &_p7, const P8 &_p8, const P9 &_p9)
242  {
243  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
244  }
245 
257  public: template< typename P1, typename P2, typename P3, typename P4,
258  typename P5, typename P6, typename P7, typename P8,
259  typename P9, typename P10 >
260  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
261  const P4 &_p4, const P5 &_p5, const P6 &_p6,
262  const P7 &_p7, const P8 &_p8, const P9 &_p9,
263  const P10 &_p10)
264  {
265  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
266  }
267 
269  public: void Signal()
270  {
271  this->Cleanup();
272 
273  this->SetSignaled(true);
274  for (const auto &iter: this->connections)
275  {
276  if (iter.second->on)
277  iter.second->callback();
278  }
279  }
280 
283  public: template< typename P >
284  void Signal(const P &_p)
285  {
286  this->Cleanup();
287 
288  this->SetSignaled(true);
289  for (const auto &iter: this->connections)
290  {
291  if (iter.second->on)
292  iter.second->callback(_p);
293  }
294  }
295 
299  public: template< typename P1, typename P2 >
300  void Signal(const P1 &_p1, const P2 &_p2)
301  {
302  this->Cleanup();
303 
304  this->SetSignaled(true);
305  for (const auto &iter: this->connections)
306  {
307  if (iter.second->on)
308  iter.second->callback(_p1, _p2);
309  }
310  }
311 
316  public: template< typename P1, typename P2, typename P3 >
317  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
318  {
319  this->Cleanup();
320 
321  this->SetSignaled(true);
322  for (const auto &iter: this->connections)
323  {
324  if (iter.second->on)
325  iter.second->callback(_p1, _p2, _p3);
326  }
327  }
328 
334  public: template<typename P1, typename P2, typename P3, typename P4>
335  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
336  const P4 &_p4)
337  {
338  this->Cleanup();
339 
340  this->SetSignaled(true);
341  for (const auto &iter: this->connections)
342  {
343  if (iter.second->on)
344  iter.second->callback(_p1, _p2, _p3, _p4);
345  }
346  }
347 
354  public: template<typename P1, typename P2, typename P3, typename P4,
355  typename P5>
356  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
357  const P4 &_p4, const P5 &_p5)
358  {
359  this->Cleanup();
360 
361  this->SetSignaled(true);
362  for (const auto &iter: this->connections)
363  {
364  if (iter.second->on)
365  iter.second->callback(_p1, _p2, _p3, _p4, _p5);
366  }
367  }
368 
376  public: template<typename P1, typename P2, typename P3, typename P4,
377  typename P5, typename P6>
378  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
379  const P4 &_p4, const P5 &_p5, const P6 &_p6)
380  {
381  this->Cleanup();
382 
383  this->SetSignaled(true);
384  for (const auto &iter: this->connections)
385  {
386  if (iter.second->on)
387  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6);
388  }
389  }
390 
399  public: template<typename P1, typename P2, typename P3, typename P4,
400  typename P5, typename P6, typename P7>
401  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
402  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7)
403  {
404  this->Cleanup();
405 
406  this->SetSignaled(true);
407  for (const auto &iter: this->connections)
408  {
409  if (iter.second->on)
410  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
411  }
412  }
413 
423  public: template<typename P1, typename P2, typename P3, typename P4,
424  typename P5, typename P6, typename P7, typename P8>
425  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
426  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
427  const P8 &_p8)
428  {
429  this->Cleanup();
430 
431  this->SetSignaled(true);
432  for (const auto &iter: this->connections)
433  {
434  if (iter.second->on)
435  {
436  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
437  }
438  }
439  }
440 
451  public: template< typename P1, typename P2, typename P3, typename P4,
452  typename P5, typename P6, typename P7, typename P8,
453  typename P9 >
454  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
455  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
456  const P8 &_p8, const P9 &_p9)
457  {
458  this->Cleanup();
459 
460  this->SetSignaled(true);
461  for (const auto &iter: this->connections)
462  {
463  if (iter.second->on)
464  {
465  iter.second->callback(
466  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
467  }
468  }
469  }
470 
482  public: template< typename P1, typename P2, typename P3, typename P4,
483  typename P5, typename P6, typename P7, typename P8,
484  typename P9, typename P10 >
485  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
486  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
487  const P8 &_p8, const P9 &_p9, const P10 &_p10)
488  {
489  this->Cleanup();
490 
491  this->SetSignaled(true);
492  for (const auto &iter: this->connections)
493  {
494  if (iter.second->on)
495  {
496  iter.second->callback(
497  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
498  }
499  }
500  }
501 
505  private: void Cleanup();
506 
508  private: class EventConnection
509  {
511  public: EventConnection(const bool _on, const std::function<T> &_cb)
512  : callback(_cb)
513  {
514  // Windows Visual Studio 2012 does not have atomic_bool constructor,
515  // so we have to set "on" using operator=
516  this->on = _on;
517  }
518 
520  public: std::atomic_bool on;
521 
523  public: std::function<T> callback;
524  };
525 
528  typedef std::map<int, std::unique_ptr<EventConnection>> EvtConnectionMap;
529 
531  private: EvtConnectionMap connections;
532 
534  private: std::mutex mutex;
535 
537  private: std::list<typename EvtConnectionMap::const_iterator>
538  connectionsToRemove;
539  };
540 
542  template<typename T>
544  : Event()
545  {
546  }
547 
549  template<typename T>
551  {
552  this->connections.clear();
553  }
554 
557  template<typename T>
558  ConnectionPtr EventT<T>::Connect(const std::function<T> &_subscriber)
559  {
560  int index = 0;
561  if (!this->connections.empty())
562  {
563  auto const &iter = this->connections.rbegin();
564  index = iter->first + 1;
565  }
566  this->connections[index].reset(new EventConnection(true, _subscriber));
567  return ConnectionPtr(new Connection(this, index));
568  }
569 
572  template<typename T>
573  unsigned int EventT<T>::ConnectionCount() const
574  {
575  return this->connections.size();
576  }
577 
580  template<typename T>
581  void EventT<T>::Disconnect(int _id)
582  {
583  // Find the connection
584  auto const &it = this->connections.find(_id);
585 
586  if (it != this->connections.end())
587  {
588  it->second->on = false;
589  this->connectionsToRemove.push_back(it);
590  }
591  }
592 
594  template<typename T>
595  void EventT<T>::Cleanup()
596  {
597  std::lock_guard<std::mutex> lock(this->mutex);
598  // Remove all queue connections.
599  for (auto &conn : this->connectionsToRemove)
600  this->connections.erase(conn);
601  this->connectionsToRemove.clear();
602  }
604  }
605 }
606 #endif
unsigned int ConnectionCount() const
Get the number of connections.
Definition: Event.hh:573
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameters.
Definition: Event.hh:156
virtual ~EventT()
Destructor.
Definition: Event.hh:550
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:170
void Signal(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:284
Base class for all events.
Definition: Event.hh:43
A class that encapsulates a connection.
Definition: Event.hh:68
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:378
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:454
virtual void Disconnect(int _id)
Disconnect a callback to this event.
Definition: Event.hh:581
void operator()()
Access the signal.
Definition: Event.hh:120
void Signal(const P1 &_p1, const P2 &_p2)
Signal the event with two parameter.
Definition: Event.hh:300
EventT()
Constructor.
Definition: Event.hh:543
void SetSignaled(const bool _sig)
Set whether this event has been signaled.
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:201
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:219
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:185
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:260
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameters.
Definition: Event.hh:145
void operator()(const P1 &_p1, const P2 &_p2)
Signal the event with two parameters.
Definition: Event.hh:135
boost::shared_ptr< Connection > ConnectionPtr
Definition: CommonTypes.hh:134
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:356
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameter.
Definition: Event.hh:317
A class for event processing.
Definition: Event.hh:97
void Signal()
Signal the event for all subscribers.
Definition: Event.hh:269
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameter.
Definition: Event.hh:335
ConnectionPtr Connect(const std::function< T > &_subscriber)
Connect a callback to this event.
Definition: Event.hh:558
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:401
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:485
void operator()(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:126
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:239
A Time class, can be used to hold wall- or sim-time.
Definition: Time.hh:44
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:425