Gazebo Gazebo

API Reference

6.16.0
gz/sim/components/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 GZ_GAZEBO_COMPONENTS_FACTORY_HH_
18 #define GZ_GAZEBO_COMPONENTS_FACTORY_HH_
19 
20 #include <cstdint>
21 #include <cstring>
22 #include <deque>
23 #include <map>
24 #include <memory>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 #include <gz/common/SingletonT.hh>
30 #include <gz/common/Util.hh>
32 #include <gz/sim/detail/ComponentStorageBase.hh>
33 #include <gz/sim/config.hh>
34 #include <gz/sim/Export.hh>
35 #include <gz/sim/Types.hh>
36 
37 namespace ignition
38 {
39 namespace gazebo
40 {
41 // Inline bracket to help doxygen filtering.
42 inline namespace IGNITION_GAZEBO_VERSION_NAMESPACE {
43 namespace components
44 {
47  {
49  public: virtual ~ComponentDescriptorBase() = default;
50 
53  public: virtual std::unique_ptr<BaseComponent> Create() const = 0;
54 
58  public: virtual std::unique_ptr<BaseComponent> Create(
59  const components::BaseComponent *_data) const = 0;
60  };
61 
64  template <typename ComponentTypeT>
67  {
69  public: std::unique_ptr<BaseComponent> Create() const override
70  {
71  return std::make_unique<ComponentTypeT>();
72  }
73 
76  const components::BaseComponent *_data) const override
77  {
78  ComponentTypeT comp(*static_cast<const ComponentTypeT *>(_data));
79  return std::make_unique<ComponentTypeT>(comp);
80  }
81  };
82 
85  {
87  public: IGN_DEPRECATED(6) StorageDescriptorBase() = default;
88 
90  public: virtual ~StorageDescriptorBase() = default;
91 
94  public: virtual std::unique_ptr<ComponentStorageBase> Create() const = 0;
95  };
96 
99  template <typename ComponentTypeT>
101  : public StorageDescriptorBase
102  {
104  public: IGN_DEPRECATED(6) StorageDescriptor() = default;
105 
110  {
111  return std::make_unique<ComponentStorage<ComponentTypeT>>();
112  }
113  };
114 
117  {
120  explicit RegistrationObjectId(void *_ptr)
121  : id(reinterpret_cast<std::uintptr_t>(_ptr))
122  {
123  }
124 
127  explicit RegistrationObjectId(std::uintptr_t _ptrAddress)
128  : id(_ptrAddress)
129  {
130  }
131 
134  bool operator==(const RegistrationObjectId &_other) const
135  {
136  return this->id == _other.id;
137  }
138 
141  };
142 
143 
159  {
161  public: bool IGNITION_GAZEBO_HIDDEN Empty()
162  {
163  return this->queue.empty();
164  }
165 
171  public: void IGNITION_GAZEBO_HIDDEN Add(RegistrationObjectId _regObjId,
173  {
174  this->queue.push_front({_regObjId, _comp});
175  }
176 
183  public: void IGNITION_GAZEBO_HIDDEN Remove(RegistrationObjectId _regObjId)
184  {
185  auto compIt = std::find_if(this->queue.rbegin(), this->queue.rend(),
186  [&](const auto &_item)
187  { return _item.first == _regObjId; });
188 
189  if (compIt != this->queue.rend())
190  {
191  ComponentDescriptorBase *compDesc = compIt->second;
192  this->queue.erase(std::prev(compIt.base()));
193  delete compDesc;
194  }
195  }
196 
200  public: IGNITION_GAZEBO_HIDDEN std::unique_ptr<BaseComponent> Create() const
201  {
202  if (!this->queue.empty())
203  {
204  return this->queue.front().second->Create();
205  }
206  return {};
207  }
208 
212  public: IGNITION_GAZEBO_HIDDEN std::unique_ptr<BaseComponent> Create(
213  const components::BaseComponent *_data) const
214  {
215  if (!this->queue.empty())
216  {
217  return this->queue.front().second->Create(_data);
218  }
219  return {};
220  }
221 
225  ComponentDescriptorBase *>> queue;
226  };
227 
229  // TODO(azeey) Do not inherit from common::SingletonT in Harmonic
230  class Factory
231  : public gz::common::SingletonT<Factory>
232  {
233  // Deleted copy constructors to make the ABI checker happy
234  public: Factory(Factory &) = delete;
235  public: Factory(const Factory &) = delete;
236  // Since the copy constructors are deleted, we need to explicitly declare a
237  // default constructor.
238  // TODO(azeey) Make this private in Harmonic
239  public: Factory() = default;
240 
242  public: IGNITION_GAZEBO_VISIBLE static Factory *Instance();
243 
252  public: template<typename ComponentTypeT>
253  void IGN_DEPRECATED(6) Register(const std::string &_type,
254  ComponentDescriptorBase *_compDesc,
255  StorageDescriptorBase * /*_storageDesc*/)
256  {
257  this->Register<ComponentTypeT>(_type, _compDesc);
258  }
259 
266  // TODO(azeey) Deprecate in favor of overload that takes _regObjId
267  public: template <typename ComponentTypeT>
268  void Register(const std::string &_type, ComponentDescriptorBase *_compDesc)
269  {
270  this->Register<ComponentTypeT>(_type, _compDesc,
271  RegistrationObjectId{nullptr});
272  }
273 
283  public: template <typename ComponentTypeT>
284  void Register(const std::string &_type, ComponentDescriptorBase *_compDesc,
285  RegistrationObjectId _regObjId)
286  {
287  auto typeHash = gz::common::hash64(_type);
288 
289  // Initialize static member variable - we need to set these
290  // static members for every shared lib that uses the component, but we
291  // only add them to the maps below once.
292  ComponentTypeT::typeId = typeHash;
293  ComponentTypeT::typeName = _type;
294 
295  // Check if component has already been registered by another library
296  auto runtimeName = typeid(ComponentTypeT).name();
297  auto runtimeNameIt = this->runtimeNamesById.find(typeHash);
298  if (runtimeNameIt != this->runtimeNamesById.end())
299  {
300  // Warn user if type was previously registered with a different name.
301  // We're leaving the ID set in case this is a false difference across
302  // libraries.
303  if (runtimeNameIt->second != runtimeName)
304  {
305  std::cerr
306  << "Registered components of different types with same name: type ["
307  << runtimeNameIt->second << "] and type [" << runtimeName
308  << "] with name [" << _type << "]. Second type will not work."
309  << std::endl;
310  return;
311  }
312  }
313 
314  // This happens at static initialization time, so we can't use common
315  // console
316  std::string debugEnv;
317  gz::common::env("IGN_DEBUG_COMPONENT_FACTORY", debugEnv);
318  if (debugEnv == "true")
319  {
320  std::cout << "Registering [" << ComponentTypeT::typeName << "]"
321  << std::endl;
322  }
323 
324  // Keep track of all types
325  this->compsById[ComponentTypeT::typeId].Add(_regObjId, _compDesc);
326  namesById[ComponentTypeT::typeId] = ComponentTypeT::typeName;
327  runtimeNamesById[ComponentTypeT::typeId] = runtimeName;
328  }
329 
333  // TODO(azeey) Deprecate in favor of overload that takes _regObjId
334  public: template <typename ComponentTypeT>
335  void Unregister()
336  {
337  this->Unregister<ComponentTypeT>(RegistrationObjectId{nullptr});
338  }
339 
346  public: template<typename ComponentTypeT>
348  {
349  this->Unregister(ComponentTypeT::typeId, _regObjId);
350  }
351 
358  // TODO(azeey) Deprecate in favor of overload that takes _regObjId
359  public: void Unregister(ComponentTypeId _typeId)
360  {
361  this->Unregister(_typeId, RegistrationObjectId{nullptr});
362  }
363 
373  public: void Unregister(ComponentTypeId _typeId,
374  RegistrationObjectId _regObjId)
375  {
376  auto it = this->compsById.find(_typeId);
377  if (it != this->compsById.end())
378  {
379  it->second.Remove(_regObjId);
380 
381  if (it->second.Empty())
382  {
383  this->compsById.erase(it);
384  }
385  }
386  }
387 
392  public: template<typename ComponentTypeT>
394  {
395  return std::unique_ptr<ComponentTypeT>(static_cast<ComponentTypeT *>(
396  this->New(ComponentTypeT::typeId).release()));
397  }
398 
404  const ComponentTypeId &_type)
405  {
406  // Create a new component if a FactoryFn has been assigned to this type.
408  auto it = this->compsById.find(_type);
409  if (it != this->compsById.end())
410  {
411  comp = it->second.Create();
412  }
413  return comp;
414  }
415 
423  const ComponentTypeId &_type, const components::BaseComponent *_data)
424  {
426 
427  if (nullptr == _data)
428  {
429  ignerr << "Requested to create a new component instance with null "
430  << "data." << std::endl;
431  }
432  else if (_type != _data->TypeId())
433  {
434  ignerr << "The typeID of _type [" << _type << "] does not match the "
435  << "typeID of _data [" << _data->TypeId() << "]." << std::endl;
436  }
437  else
438  {
439  auto it = this->compsById.find(_type);
440  if (it != this->compsById.end())
441  {
442  comp = it->second.Create(_data);
443  }
444  }
445 
446  return comp;
447  }
448 
454  const ComponentTypeId & /*_typeId*/)
455  {
456  return nullptr;
457  }
458 
462  {
464 
465  // Return the list of all known component types.
466  for (const auto &comp : this->compsById)
467  types.push_back(comp.first);
468 
469  return types;
470  }
471 
474  public: bool HasType(ComponentTypeId _typeId)
475  {
476  return this->compsById.find(_typeId) != this->compsById.end();
477  }
478 
481  public: std::string Name(ComponentTypeId _typeId) const
482  {
483  if (this->namesById.find(_typeId) != this->namesById.end())
484  return namesById.at(_typeId);
485 
486  return "";
487  }
488 
491 
494 
499  };
500 
509  #define IGN_GAZEBO_REGISTER_COMPONENT(_compType, _classname) \
510  class IgnGazeboComponents##_classname \
511  { \
512  public: IgnGazeboComponents##_classname() \
513  { \
514  using namespace ignition; \
515  using Desc = gz::sim::components::ComponentDescriptor<_classname>; \
516  gz::sim::components::Factory::Instance()->Register<_classname>(\
517  _compType, new Desc(), \
518  gz::sim::components::RegistrationObjectId(this));\
519  } \
520  public: IgnGazeboComponents##_classname( \
521  const IgnGazeboComponents##_classname&) = delete; \
522  public: IgnGazeboComponents##_classname( \
523  IgnGazeboComponents##_classname&) = delete; \
524  public: ~IgnGazeboComponents##_classname() \
525  { \
526  using namespace ignition; \
527  gazebo::components::Factory::Instance()->Unregister<_classname>( \
528  gazebo::components::RegistrationObjectId(this)); \
529  } \
530  }; \
531  static IgnGazeboComponents##_classname\
532  IgnitionGazeboComponentsInitializer##_classname;
533 }
534 }
535 }
536 }
537 
538 #endif
virtual ~ComponentDescriptorBase()=default
Destructor.
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: gz/sim/components/Factory.hh:498
#define IGN_DEPRECATED(version)
This library is part of the Gazebo project.
STL class.
std::unique_ptr< ComponentTypeT > New()
Create a new instance of a component.
Definition: gz/sim/components/Factory.hh:393
std::uintptr_t id
Wrapped uintptr_t variable.
Definition: gz/sim/components/Factory.hh:140
void IGNITION_GAZEBO_HIDDEN Remove(RegistrationObjectId _regObjId)
Remove a component descriptor from the queue. This also deletes memory allocated for the component de...
Definition: gz/sim/components/Factory.hh:183
void Unregister(ComponentTypeId _typeId, RegistrationObjectId _regObjId)
Unregister a component so that the factory can't create instances of the component anymore.
Definition: gz/sim/components/Factory.hh:373
A class to hold the queue of component descriptors registered by translation units....
Definition: gz/sim/components/Factory.hh:158
std::map< ComponentTypeId, std::string > namesById
A list of IDs and their equivalent names.
Definition: gz/sim/components/Factory.hh:493
void Unregister()
Unregister a component so that the factory can't create instances of the component anymore.
Definition: gz/sim/components/Factory.hh:335
std::string Name(ComponentTypeId _typeId) const
Get a component's type name given its type ID. return Unique component name.
Definition: gz/sim/components/Factory.hh:481
STL class.
T find_if(T... args)
void Unregister(ComponentTypeId _typeId)
Unregister a component so that the factory can't create instances of the component anymore.
Definition: gz/sim/components/Factory.hh:359
IGNITION_GAZEBO_HIDDEN std::unique_ptr< BaseComponent > Create() const
Create a component using the latest available component descriptor. This simply forward to ComponentD...
Definition: gz/sim/components/Factory.hh:200
RegistrationObjectId(std::uintptr_t _ptrAddress)
Construct object from a uintptr_t.
Definition: gz/sim/components/Factory.hh:127
void Register(const std::string &_type, ComponentDescriptorBase *_compDesc, RegistrationObjectId _regObjId)
Register a component so that the factory can create instances of the component based on an ID.
Definition: gz/sim/components/Factory.hh:284
virtual std::unique_ptr< BaseComponent > Create() const =0
Create an instance of a Component.
std::unique_ptr< ComponentStorageBase > Create() const override
Create an instance of a storage that holds ComponentTypeT components.
Definition: gz/sim/components/Factory.hh:109
void Unregister(RegistrationObjectId _regObjId)
Unregister a component so that the factory can't create instances of the component anymore.
Definition: gz/sim/components/Factory.hh:347
A factory that generates a component based on a string type.
Definition: gz/sim/components/Factory.hh:230
std::unique_ptr< ComponentStorageBase > NewStorage(const ComponentTypeId &)
Create a new instance of a component storage.
Definition: gz/sim/components/Factory.hh:453
#define ignerr
T push_back(T... args)
std::unique_ptr< components::BaseComponent > New(const ComponentTypeId &_type, const components::BaseComponent *_data)
Create a new instance of a component, initialized with particular data.
Definition: gz/sim/components/Factory.hh:422
virtual ComponentTypeId TypeId() const =0
Returns the unique ID for the component's type. The ID is derived from the name that is manually chos...
A base class for an object responsible for creating components.
Definition: gz/sim/components/Factory.hh:46
T at(T... args)
bool operator==(const RegistrationObjectId &_other) const
Equality comparison.
Definition: gz/sim/components/Factory.hh:134
A class for an object responsible for creating components.
Definition: gz/sim/components/Factory.hh:65
virtual std::unique_ptr< BaseComponent > Create(const components::BaseComponent *_data) const override
Documentation inherited.
Definition: gz/sim/components/Factory.hh:75
STL class.
Base class for all components.
Definition: gz/sim/components/Component.hh:230
RegistrationObjectId(void *_ptr)
Construct object from a pointer.
Definition: gz/sim/components/Factory.hh:120
std::unique_ptr< BaseComponent > Create() const override
Documentation inherited.
Definition: gz/sim/components/Factory.hh:69
STL class.
IGNITION_GAZEBO_HIDDEN std::unique_ptr< BaseComponent > Create(const components::BaseComponent *_data) const
Create a component using the latest available component descriptor. This simply forward to ComponentD...
Definition: gz/sim/components/Factory.hh:212
std::unique_ptr< components::BaseComponent > New(const ComponentTypeId &_type)
Create a new instance of a component.
Definition: gz/sim/components/Factory.hh:403
virtual ~StorageDescriptorBase()=default
Destructor.
T endl(T... args)
bool HasType(ComponentTypeId _typeId)
Check if a component type has been registered. return True if registered.
Definition: gz/sim/components/Factory.hh:474
static Factory * Instance()
Get an instance of the singleton.
STL namespace.
A wrapper around uintptr_t to prevent implicit conversions.
Definition: gz/sim/components/Factory.hh:116
bool IGNITION_GAZEBO_HIDDEN Empty()
Check if the queue is empty.
Definition: gz/sim/components/Factory.hh:161
void Register(const std::string &_type, ComponentDescriptorBase *_compDesc)
Register a component so that the factory can create instances of the component based on an ID.
Definition: gz/sim/components/Factory.hh:268
std::vector< ComponentTypeId > TypeIds() const
Get all the registered component types by ID. return Vector of component IDs.
Definition: gz/sim/components/Factory.hh:461
T end(T... args)
T prev(T... args)
A base class for an object responsible for creating storages.
Definition: gz/sim/components/Factory.hh:84
uint64_t ComponentTypeId
A unique identifier for a component type. A component type must be derived from components::BaseCompo...
Definition: include/gz/sim/Types.hh:90
STL class.
void Register(const std::string &_type, ComponentDescriptorBase *_compDesc, StorageDescriptorBase *)
Register a component so that the factory can create instances of the component and its storage based ...
Definition: gz/sim/components/Factory.hh:253
virtual std::unique_ptr< ComponentStorageBase > Create() const =0
Create an instance of a storage.
void IGNITION_GAZEBO_HIDDEN Add(RegistrationObjectId _regObjId, ComponentDescriptorBase *_comp)
Add a component descriptor to the queue.
Definition: gz/sim/components/Factory.hh:171
A class for an object responsible for creating storages.
Definition: gz/sim/components/Factory.hh:100