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 
54  public: virtual void Disconnect(ConnectionPtr _c)
55  GAZEBO_DEPRECATED(8.0) = 0;
56 
59  public: virtual void Disconnect(int _id) = 0;
60 
64  public: bool GetSignaled() const GAZEBO_DEPRECATED(8.0);
65 
68  public: bool Signaled() const;
69 
72  public: void SetSignaled(const bool _sig);
73 
75  private: bool signaled;
76  };
77 
79  class GZ_COMMON_VISIBLE Connection
80  {
84  public: Connection(Event *_e, const int _i);
85 
87  public: ~Connection();
88 
92  public: int GetId() const GAZEBO_DEPRECATED(8.0);
93 
96  public: int Id() const;
97 
99  private: Event *event = nullptr;
100 
102  private: int id = -1;
103 
105  private: common::Time creationTime;
106 
108  public: template<typename T> friend class EventT;
109  };
110 
112  template<typename T>
113  class EventT : public Event
114  {
116  public: EventT();
117 
119  public: virtual ~EventT();
120 
125  public: ConnectionPtr Connect(const std::function<T> &_subscriber);
126 
130  public: virtual void Disconnect(ConnectionPtr _c)
131  GAZEBO_DEPRECATED(8.0);
132 
135  public: virtual void Disconnect(int _id);
136 
139  public: unsigned int ConnectionCount() const;
140 
142  public: void operator()()
143  {this->Signal();}
144 
147  public: template< typename P >
148  void operator()(const P &_p)
149  {
150  this->Signal(_p);
151  }
152 
156  public: template< typename P1, typename P2 >
157  void operator()(const P1 &_p1, const P2 &_p2)
158  {
159  this->Signal(_p1, _p2);
160  }
161 
166  public: template< typename P1, typename P2, typename P3 >
167  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
168  {
169  this->Signal(_p1, _p2, _p3);
170  }
171 
177  public: template< typename P1, typename P2, typename P3, typename P4 >
178  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
179  const P4 &_p4)
180  {
181  this->Signal(_p1, _p2, _p3, _p4);
182  }
183 
190  public: template< typename P1, typename P2, typename P3, typename P4,
191  typename P5 >
192  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
193  const P4 &_p4, const P5 &_p5)
194  {
195  this->Signal(_p1, _p2, _p3, _p4, _p5);
196  }
197 
205  public: template< typename P1, typename P2, typename P3, typename P4,
206  typename P5, typename P6 >
207  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
208  const P4 &_p4, const P5 &_p5, const P6 &_p6)
209  {
210  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6);
211  }
212 
221  public: template< typename P1, typename P2, typename P3, typename P4,
222  typename P5, typename P6, typename P7 >
223  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
224  const P4 &_p4, const P5 &_p5, const P6 &_p6,
225  const P7 &_p7)
226  {
227  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
228  }
229 
239  public: template< typename P1, typename P2, typename P3, typename P4,
240  typename P5, typename P6, typename P7, typename P8 >
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)
244  {
245  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
246  }
247 
258  public: template< typename P1, typename P2, typename P3, typename P4,
259  typename P5, typename P6, typename P7, typename P8,
260  typename P9 >
261  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
262  const P4 &_p4, const P5 &_p5, const P6 &_p6,
263  const P7 &_p7, const P8 &_p8, const P9 &_p9)
264  {
265  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
266  }
267 
279  public: template< typename P1, typename P2, typename P3, typename P4,
280  typename P5, typename P6, typename P7, typename P8,
281  typename P9, typename P10 >
282  void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3,
283  const P4 &_p4, const P5 &_p5, const P6 &_p6,
284  const P7 &_p7, const P8 &_p8, const P9 &_p9,
285  const P10 &_p10)
286  {
287  this->Signal(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
288  }
289 
291  public: void Signal()
292  {
293  this->Cleanup();
294 
295  this->SetSignaled(true);
296  for (const auto &iter: this->connections)
297  {
298  if (iter.second->on)
299  iter.second->callback();
300  }
301  }
302 
305  public: template< typename P >
306  void Signal(const P &_p)
307  {
308  this->Cleanup();
309 
310  this->SetSignaled(true);
311  for (const auto &iter: this->connections)
312  {
313  if (iter.second->on)
314  iter.second->callback(_p);
315  }
316  }
317 
321  public: template< typename P1, typename P2 >
322  void Signal(const P1 &_p1, const P2 &_p2)
323  {
324  this->Cleanup();
325 
326  this->SetSignaled(true);
327  for (const auto &iter: this->connections)
328  {
329  if (iter.second->on)
330  iter.second->callback(_p1, _p2);
331  }
332  }
333 
338  public: template< typename P1, typename P2, typename P3 >
339  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
340  {
341  this->Cleanup();
342 
343  this->SetSignaled(true);
344  for (const auto &iter: this->connections)
345  {
346  if (iter.second->on)
347  iter.second->callback(_p1, _p2, _p3);
348  }
349  }
350 
356  public: template<typename P1, typename P2, typename P3, typename P4>
357  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
358  const P4 &_p4)
359  {
360  this->Cleanup();
361 
362  this->SetSignaled(true);
363  for (const auto &iter: this->connections)
364  {
365  if (iter.second->on)
366  iter.second->callback(_p1, _p2, _p3, _p4);
367  }
368  }
369 
376  public: template<typename P1, typename P2, typename P3, typename P4,
377  typename P5>
378  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
379  const P4 &_p4, const P5 &_p5)
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);
388  }
389  }
390 
398  public: template<typename P1, typename P2, typename P3, typename P4,
399  typename P5, typename P6>
400  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
401  const P4 &_p4, const P5 &_p5, const P6 &_p6)
402  {
403  this->Cleanup();
404 
405  this->SetSignaled(true);
406  for (const auto &iter: this->connections)
407  {
408  if (iter.second->on)
409  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6);
410  }
411  }
412 
421  public: template<typename P1, typename P2, typename P3, typename P4,
422  typename P5, typename P6, typename P7>
423  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
424  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7)
425  {
426  this->Cleanup();
427 
428  this->SetSignaled(true);
429  for (const auto &iter: this->connections)
430  {
431  if (iter.second->on)
432  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7);
433  }
434  }
435 
445  public: template<typename P1, typename P2, typename P3, typename P4,
446  typename P5, typename P6, typename P7, typename P8>
447  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
448  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
449  const P8 &_p8)
450  {
451  this->Cleanup();
452 
453  this->SetSignaled(true);
454  for (const auto &iter: this->connections)
455  {
456  if (iter.second->on)
457  {
458  iter.second->callback(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8);
459  }
460  }
461  }
462 
473  public: template< typename P1, typename P2, typename P3, typename P4,
474  typename P5, typename P6, typename P7, typename P8,
475  typename P9 >
476  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
477  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
478  const P8 &_p8, const P9 &_p9)
479  {
480  this->Cleanup();
481 
482  this->SetSignaled(true);
483  for (const auto &iter: this->connections)
484  {
485  if (iter.second->on)
486  {
487  iter.second->callback(
488  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);
489  }
490  }
491  }
492 
504  public: template< typename P1, typename P2, typename P3, typename P4,
505  typename P5, typename P6, typename P7, typename P8,
506  typename P9, typename P10 >
507  void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3,
508  const P4 &_p4, const P5 &_p5, const P6 &_p6, const P7 &_p7,
509  const P8 &_p8, const P9 &_p9, const P10 &_p10)
510  {
511  this->Cleanup();
512 
513  this->SetSignaled(true);
514  for (const auto &iter: this->connections)
515  {
516  if (iter.second->on)
517  {
518  iter.second->callback(
519  _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9, _p10);
520  }
521  }
522  }
523 
527  private: void Cleanup();
528 
530  private: class EventConnection
531  {
533  public: EventConnection(const bool _on, const std::function<T> &_cb)
534  : callback(_cb)
535  {
536  // Windows Visual Studio 2012 does not have atomic_bool constructor,
537  // so we have to set "on" using operator=
538  this->on = _on;
539  }
540 
542  public: std::atomic_bool on;
543 
545  public: std::function<T> callback;
546  };
547 
550  typedef std::map<int, std::unique_ptr<EventConnection>> EvtConnectionMap;
551 
553  private: EvtConnectionMap connections;
554 
556  private: std::mutex mutex;
557 
559  private: std::list<typename EvtConnectionMap::const_iterator>
560  connectionsToRemove;
561  };
562 
564  template<typename T>
566  : Event()
567  {
568  }
569 
571  template<typename T>
573  {
574  this->connections.clear();
575  }
576 
579  template<typename T>
580  ConnectionPtr EventT<T>::Connect(const std::function<T> &_subscriber)
581  {
582  int index = 0;
583  if (!this->connections.empty())
584  {
585  auto const &iter = this->connections.rbegin();
586  index = iter->first + 1;
587  }
588  this->connections[index].reset(new EventConnection(true, _subscriber));
589  return ConnectionPtr(new Connection(this, index));
590  }
591 
594  template<typename T>
596  {
597  if (!_c)
598  return;
599 
600  this->Disconnect(_c->Id());
601  _c->event = nullptr;
602  _c->id = -1;
603  }
604 
607  template<typename T>
608  unsigned int EventT<T>::ConnectionCount() const
609  {
610  return this->connections.size();
611  }
612 
615  template<typename T>
616  void EventT<T>::Disconnect(int _id)
617  {
618  // Find the connection
619  auto const &it = this->connections.find(_id);
620 
621  if (it != this->connections.end())
622  {
623  it->second->on = false;
624  this->connectionsToRemove.push_back(it);
625  }
626  }
627 
629  template<typename T>
630  void EventT<T>::Cleanup()
631  {
632  std::lock_guard<std::mutex> lock(this->mutex);
633  // Remove all queue connections.
634  for (auto &conn : this->connectionsToRemove)
635  this->connections.erase(conn);
636  this->connectionsToRemove.clear();
637  }
639  }
640 }
641 #endif
unsigned int ConnectionCount() const
Get the number of connections.
Definition: Event.hh:608
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameters.
Definition: Event.hh:178
virtual ~EventT()
Destructor.
Definition: Event.hh:572
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:192
void Signal(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:306
Base class for all events.
Definition: Event.hh:43
A class that encapsulates a connection.
Definition: Event.hh:79
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:400
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:476
void operator()()
Access the signal.
Definition: Event.hh:142
void Signal(const P1 &_p1, const P2 &_p2)
Signal the event with two parameter.
Definition: Event.hh:322
virtual void Disconnect(ConnectionPtr _c) GAZEBO_DEPRECATED(8.0)
Disconnect a callback to this event.
Definition: Event.hh:595
EventT()
Constructor.
Definition: Event.hh:565
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:223
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:241
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:207
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:282
void operator()(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameters.
Definition: Event.hh:167
void operator()(const P1 &_p1, const P2 &_p2)
Signal the event with two parameters.
Definition: Event.hh:157
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:378
#define GAZEBO_DEPRECATED(version)
Definition: system.hh:302
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3)
Signal the event with three parameter.
Definition: Event.hh:339
A class for event processing.
Definition: Event.hh:113
void Signal()
Signal the event for all subscribers.
Definition: Event.hh:291
void Signal(const P1 &_p1, const P2 &_p2, const P3 &_p3, const P4 &_p4)
Signal the event with four parameter.
Definition: Event.hh:357
ConnectionPtr Connect(const std::function< T > &_subscriber)
Connect a callback to this event.
Definition: Event.hh:580
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:423
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:507
void operator()(const P &_p)
Signal the event with one parameter.
Definition: Event.hh:148
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:261
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:447