Ignition Gazebo

API Reference

5.0.0
Factory.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 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 IGNITION_GAZEBO_COMPONENTS_FACTORY_HH_
18 #define IGNITION_GAZEBO_COMPONENTS_FACTORY_HH_
19 
20 #include <cstdint>
21 #include <cstring>
22 #include <map>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
28 #include <ignition/common/Util.hh>
30 #include <ignition/gazebo/detail/ComponentStorageBase.hh>
31 #include <ignition/gazebo/config.hh>
32 #include <ignition/gazebo/Export.hh>
33 #include <ignition/gazebo/Types.hh>
34 
35 namespace ignition
36 {
37 namespace gazebo
38 {
39 // Inline bracket to help doxygen filtering.
40 inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
41 namespace components
42 {
45  {
47  public: virtual ~ComponentDescriptorBase() = default;
48 
51  public: virtual std::unique_ptr<BaseComponent> Create() const = 0;
52  };
53 
56  template <typename ComponentTypeT>
59  {
62  public: std::unique_ptr<BaseComponent> Create() const override
63  {
64  return std::make_unique<ComponentTypeT>();
65  }
66  };
67 
70  {
72  public: virtual ~StorageDescriptorBase() = default;
73 
76  public: virtual std::unique_ptr<ComponentStorageBase> Create() const = 0;
77  };
78 
81  template <typename ComponentTypeT>
83  : public StorageDescriptorBase
84  {
89  {
90  return std::make_unique<ComponentStorage<ComponentTypeT>>();
91  }
92  };
93 
95  class Factory
96  : public ignition::common::SingletonT<Factory>
97  {
106  public: template<typename ComponentTypeT>
107  void Register(const std::string &_type, ComponentDescriptorBase *_compDesc,
108  StorageDescriptorBase *_storageDesc)
109  {
110  // Every time a plugin which uses a component type is loaded, it attempts
111  // to register it again, so we skip it.
112  if (ComponentTypeT::typeId != 0)
113  {
114  return;
115  }
116 
117  auto typeHash = ignition::common::hash64(_type);
118 
119  // Initialize static member variable - we need to set these
120  // static members for every shared lib that uses the component, but we
121  // only add them to the maps below once.
122  ComponentTypeT::typeId = typeHash;
123  ComponentTypeT::typeName = _type;
124 
125  // Check if component has already been registered by another library
126  auto runtimeName = typeid(ComponentTypeT).name();
127  auto runtimeNameIt = this->runtimeNamesById.find(typeHash);
128  if (runtimeNameIt != this->runtimeNamesById.end())
129  {
130  // Warn user if type was previously registered with a different name.
131  // We're leaving the ID set in case this is a false difference across
132  // libraries.
133  if (runtimeNameIt->second != runtimeName)
134  {
135  std::cerr
136  << "Registered components of different types with same name: type ["
137  << runtimeNameIt->second << "] and type [" << runtimeName
138  << "] with name [" << _type << "]. Second type will not work."
139  << std::endl;
140  }
141  return;
142  }
143 
144  // This happens at static initialization time, so we can't use common
145  // console
146  std::string debugEnv;
147  ignition::common::env("IGN_DEBUG_COMPONENT_FACTORY", debugEnv);
148  if (debugEnv == "true")
149  {
150  std::cout << "Registering [" << ComponentTypeT::typeName << "]"
151  << std::endl;
152  }
153 
154  // Keep track of all types
155  this->compsById[ComponentTypeT::typeId] = _compDesc;
156  this->storagesById[ComponentTypeT::typeId] = _storageDesc;
157  namesById[ComponentTypeT::typeId] = ComponentTypeT::typeName;
158  runtimeNamesById[ComponentTypeT::typeId] = runtimeName;
159  }
160 
164  public: template<typename ComponentTypeT>
165  void Unregister()
166  {
167  this->Unregister(ComponentTypeT::typeId);
168 
169  ComponentTypeT::typeId = 0;
170  }
171 
178  public: void Unregister(ComponentTypeId _typeId)
179  {
180  // Not registered
181  if (_typeId == 0)
182  {
183  return;
184  }
185 
186  {
187  auto it = this->compsById.find(_typeId);
188  if (it != this->compsById.end())
189  {
190  delete it->second;
191  this->compsById.erase(it);
192  }
193  }
194 
195  {
196  auto it = this->storagesById.find(_typeId);
197  if (it != this->storagesById.end())
198  {
199  delete it->second;
200  this->storagesById.erase(it);
201  }
202  }
203 
204  {
205  auto it = namesById.find(_typeId);
206  if (it != namesById.end())
207  {
208  namesById.erase(it);
209  }
210  }
211 
212  {
213  auto it = runtimeNamesById.find(_typeId);
214  if (it != runtimeNamesById.end())
215  {
216  runtimeNamesById.erase(it);
217  }
218  }
219  }
220 
225  public: template<typename ComponentTypeT>
227  {
228  return std::unique_ptr<ComponentTypeT>(static_cast<ComponentTypeT *>(
229  this->New(ComponentTypeT::typeId).release()));
230  }
231 
237  const ComponentTypeId &_type)
238  {
239  // Create a new component if a FactoryFn has been assigned to this type.
241  auto it = this->compsById.find(_type);
242  if (it != this->compsById.end() && nullptr != it->second)
243  comp = it->second->Create();
244 
245  return comp;
246  }
247 
253  const ComponentTypeId &_typeId)
254  {
256  auto it = this->storagesById.find(_typeId);
257  if (it != this->storagesById.end() && nullptr != it->second)
258  storage = it->second->Create();
259 
260  return storage;
261  }
262 
266  {
268 
269  // Return the list of all known component types.
270  for (const auto &comp : this->compsById)
271  types.push_back(comp.first);
272 
273  return types;
274  }
275 
278  public: bool HasType(ComponentTypeId _typeId)
279  {
280  return this->compsById.find(_typeId) != this->compsById.end();
281  }
282 
285  public: std::string Name(ComponentTypeId _typeId) const
286  {
287  if (this->namesById.find(_typeId) != this->namesById.end())
288  return namesById.at(_typeId);
289 
290  return "";
291  }
292 
307 
311 
314 
319  };
320 
329  #define IGN_GAZEBO_REGISTER_COMPONENT(_compType, _classname) \
330  class IgnGazeboComponents##_classname \
331  { \
332  public: IgnGazeboComponents##_classname() \
333  { \
334  if (_classname::typeId != 0) \
335  return; \
336  using namespace ignition;\
337  using Desc = gazebo::components::ComponentDescriptor<_classname>; \
338  using StorageDesc = gazebo::components::StorageDescriptor<_classname>; \
339  gazebo::components::Factory::Instance()->Register<_classname>(\
340  _compType, new Desc(), new StorageDesc());\
341  } \
342  }; \
343  static IgnGazeboComponents##_classname\
344  IgnitionGazeboComponentsInitializer##_classname;
345 }
346 }
347 }
348 }
349 
350 #endif
std::unique_ptr< ComponentStorageBase > NewStorage(const ComponentTypeId &_typeId)
Create a new instance of a component storage.
Definition: Factory.hh:252
std::map< ComponentTypeId, std::string > namesById
A list of IDs and their equivalent names.
Definition: Factory.hh:313
A base class for an object responsible for creating storages.
Definition: Factory.hh:69
std::vector< ComponentTypeId > TypeIds() const
Get all the registered component types by ID. return Vector of component IDs.
Definition: Factory.hh:265
T endl(T... args)
void Register(const std::string &_type, ComponentDescriptorBase *_compDesc, StorageDescriptorBase *_storageDesc)
Register a component so that the factory can create instances of the component and its storage based ...
Definition: Factory.hh:107
bool HasType(ComponentTypeId _typeId)
Check if a component type has been registered. return True if registered.
Definition: Factory.hh:278
STL class.
std::unique_ptr< BaseComponent > Create() const override
Create an instance of a ComponentTypeT Component.
Definition: Factory.hh:62
A factory that generates a component based on a string type.
Definition: Factory.hh:95
STL class.
bool env(const std::string &_name, std::string &_value)
T at(T... args)
T push_back(T... args)
void Unregister(ComponentTypeId _typeId)
Unregister a component so that the factory can&#39;t create instances of the component or its storage any...
Definition: Factory.hh:178
void Unregister()
Unregister a component so that the factory can&#39;t create instances of the component or its storage any...
Definition: Factory.hh:165
std::unique_ptr< ComponentStorageBase > Create() const override
Create an instance of a storage that holds ComponentTypeT components.
Definition: Factory.hh:88
constexpr uint64_t hash64(std::string_view _key)
std::map< ComponentTypeId, std::string > runtimeNamesById
Keep track of the runtime names for types and warn the user if they try to register different types w...
Definition: Factory.hh:318
uint64_t ComponentTypeId
A unique identifier for a component type. A component type must be derived from components::BaseCompo...
Definition: Types.hh:86
T find(T... args)
std::unique_ptr< ComponentTypeT > New()
Create a new instance of a component.
Definition: Factory.hh:226
STL class.
STL class.
std::unique_ptr< components::BaseComponent > New(const ComponentTypeId &_type)
Create a new instance of a component.
Definition: Factory.hh:236
A base class for an object responsible for creating components.
Definition: Factory.hh:44
This library is part of the Ignition Robotics project.
A class for an object responsible for creating components.
Definition: Factory.hh:57
A class for an object responsible for creating storages.
Definition: Factory.hh:82
std::string Name(ComponentTypeId _typeId) const
Get a component&#39;s type name given its type ID. return Unique component name.
Definition: Factory.hh:285