Gazebo Sim

API Reference

9.0.0
EventManager.hh
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018 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 GZ_SIM_EVENTMANAGER_HH_
18#define GZ_SIM_EVENTMANAGER_HH_
19
20#include <functional>
21#include <memory>
22#include <typeinfo>
23#include <unordered_map>
24#include <utility>
25
26#include <gz/common/Console.hh>
27#include <gz/common/Event.hh>
28
29#include <gz/sim/config.hh>
30#include <gz/sim/Export.hh>
31#include <gz/sim/Types.hh>
32
33namespace gz
34{
35 namespace sim
36 {
37 // Inline bracket to help doxygen filtering.
38 inline namespace GZ_SIM_VERSION_NAMESPACE {
39 // Forward declarations.
40 class GZ_SIM_HIDDEN EventManagerPrivate;
41
50
55 {
57 public: EventManager() = default;
58
59 public: EventManager(const EventManager &) = delete;
60 public: EventManager &operator=(const EventManager &) = delete;
61
63 public: ~EventManager() = default;
64
70 public: template <typename E>
72 Connect(const typename E::CallbackT &_subscriber)
73 {
74 if (this->events.find(typeid(E)) == this->events.end()) {
75 this->events[typeid(E)] = std::make_unique<E>();
76 }
77
78 E *eventPtr = dynamic_cast<E *>(this->events[typeid(E)].get());
79 // All values in the map should be derived from Event,
80 // so this shouldn't be an issue, but it doesn't hurt to check.
81 if (eventPtr != nullptr)
82 {
83 return eventPtr->Connect(_subscriber);
84 }
85 else
86 {
87 gzerr << "Failed to connect event: "
88 << typeid(E).name() << std::endl;
89 return nullptr;
90 }
91 }
92
96 public: template <typename E, typename ... Args>
97 void Emit(Args && ... _args)
98 {
99 if (this->events.find(typeid(E)) == this->events.end())
100 {
101 // If there are no events of type E in the map, create it.
102 // But it also means there is nothing to signal.
103 //
104 // This is also needed to suppress unused function warnings
105 // for Events that are purely emitted, with no connections.
106 this->events[typeid(E)] = std::make_unique<E>();
107 return;
108 }
109
110 E *eventPtr = dynamic_cast<E *>(this->events[typeid(E)].get());
111 // All values in the map should be derived from Event,
112 // so this shouldn't be an issue, but it doesn't hurt to check.
113 if (eventPtr != nullptr)
114 {
115 eventPtr->Signal(std::forward<Args>(_args) ...);
116 }
117 else
118 {
119 gzerr << "Failed to signal event: "
120 << typeid(E).name() << std::endl;
121 }
122 }
123
126 public: template <typename E>
127 unsigned int
129 {
130 if (this->events.find(typeid(E)) == this->events.end())
131 {
132 return 0u;
133 }
134
135 E *eventPtr = dynamic_cast<E *>(this->events[typeid(E)].get());
136 // All values in the map should be derived from Event,
137 // so this shouldn't be an issue, but it doesn't hurt to check.
138 if (eventPtr != nullptr)
139 {
140 return eventPtr->ConnectionCount();
141 }
142 else
143 {
144 gzerr << "Failed to get connection count for event: "
145 << typeid(E).name() << std::endl;
146 return 0u;
147 }
148 }
149
151 private: using TypeInfoRef = std::reference_wrapper<const std::type_info>;
152
154 private: struct Hasher
155 {
156 std::size_t operator()(TypeInfoRef _code) const
157 {
158 return _code.get().hash_code();
159 }
160 };
161
163 private: struct EqualTo
164 {
165 bool operator()(TypeInfoRef _lhs, TypeInfoRef _rhs) const
166 {
167 return _lhs.get() == _rhs.get();
168 }
169 };
170
172 private: std::unordered_map<TypeInfoRef,
174 Hasher, EqualTo> events;
175 };
176 }
177 }
178}
179
180#endif // GZ_SIM_EVENTMANAGER_HH_