Gazebo Sim

API Reference

10.4.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 <cstring>
21#include <functional>
22#include <memory>
23#include <string>
24#include <typeinfo>
25#include <unordered_map>
26#include <utility>
27
28#include <gz/common/Console.hh>
29#include <gz/common/Event.hh>
30
31#include <gz/sim/config.hh>
32#include <gz/sim/Export.hh>
33#include <gz/sim/Types.hh>
34
35namespace gz
36{
37 namespace sim
38 {
39 // Inline bracket to help doxygen filtering.
40 inline namespace GZ_SIM_VERSION_NAMESPACE {
41 // Forward declarations.
42 class GZ_SIM_HIDDEN EventManagerPrivate;
43
52
57 {
59 public: EventManager() = default;
60
61 public: EventManager(const EventManager &) = delete;
62 public: EventManager &operator=(const EventManager &) = delete;
63
65 public: ~EventManager() = default;
66
72 public: template <typename E>
74 Connect(const typename E::CallbackT &_subscriber)
75 {
76 if (this->events.find(typeid(E)) == this->events.end()) {
77 this->events[typeid(E)] = std::make_unique<E>();
78 }
79
80 // static_cast is used instead of dynamic_cast because
81 // dynamic_cast fails across shared-library boundaries when
82 // plugins are loaded with RTLD_LOCAL and hidden visibility
83 // (the RTTI type_info pointers differ per dylib on macOS).
84 // The map key guarantees the correct type by construction.
85 E *eventPtr = static_cast<E *>(this->events[typeid(E)].get());
86 return eventPtr->Connect(_subscriber);
87 }
88
92 public: template <typename E, typename ... Args>
93 void Emit(Args && ... _args)
94 {
95 if (this->events.find(typeid(E)) == this->events.end())
96 {
97 // If there are no events of type E in the map, create it.
98 // But it also means there is nothing to signal.
99 //
100 // This is also needed to suppress unused function warnings
101 // for Events that are purely emitted, with no connections.
102 this->events[typeid(E)] = std::make_unique<E>();
103 return;
104 }
105
106 // static_cast: see Connect() comment on RTTI across dylibs.
107 E *eventPtr = static_cast<E *>(this->events[typeid(E)].get());
108 eventPtr->Signal(std::forward<Args>(_args) ...);
109 }
110
113 public: template <typename E>
114 unsigned int
116 {
117 if (this->events.find(typeid(E)) == this->events.end())
118 {
119 return 0u;
120 }
121
122 // static_cast: see Connect() comment on RTTI across dylibs.
123 E *eventPtr = static_cast<E *>(this->events[typeid(E)].get());
124 return eventPtr->ConnectionCount();
125 }
126
128 private: using TypeInfoRef = std::reference_wrapper<const std::type_info>;
129
134 private: struct Hasher
135 {
136 std::size_t operator()(TypeInfoRef _code) const
137 {
138 return std::hash<std::string>{}(_code.get().name());
139 }
140 };
141
143 private: struct EqualTo
144 {
145 bool operator()(TypeInfoRef _lhs, TypeInfoRef _rhs) const
146 {
147 return _lhs.get() == _rhs.get() ||
148 std::strcmp(_lhs.get().name(),
149 _rhs.get().name()) == 0;
150 }
151 };
152
154 private: std::unordered_map<TypeInfoRef,
156 Hasher, EqualTo> events;
157 };
158 }
159 }
160}
161
162#endif // GZ_SIM_EVENTMANAGER_HH_