Gazebo Gazebo

API Reference

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