17 #ifndef GZ_SIM_COMPONENTS_FACTORY_HH_
18 #define GZ_SIM_COMPONENTS_FACTORY_HH_
29 #include <gz/common/SingletonT.hh>
30 #include <gz/common/Util.hh>
32 #include <gz/sim/config.hh>
33 #include <gz/sim/Export.hh>
41 inline namespace GZ_SIM_VERSION_NAMESPACE {
63 template <
typename ComponentTypeT>
70 return std::make_unique<ComponentTypeT>();
77 ComponentTypeT comp(*
static_cast<const ComponentTypeT *
>(_data));
78 return std::make_unique<ComponentTypeT>(comp);
88 : id(reinterpret_cast<
std::uintptr_t>(_ptr))
103 return this->
id == _other.
id;
130 return this->queue.empty();
141 this->queue.push_front({_regObjId, _comp});
152 auto compIt =
std::find_if(this->queue.rbegin(), this->queue.rend(),
153 [&](
const auto &_item)
154 { return _item.first == _regObjId; });
156 if (compIt != this->queue.rend())
159 this->queue.erase(
std::prev(compIt.base()));
169 if (!this->queue.empty())
171 return this->queue.front().second->Create();
182 if (!this->queue.empty())
184 return this->queue.front().second->Create(_data);
209 public: GZ_SIM_VISIBLE
static Factory *Instance();
218 public:
template <
typename ComponentTypeT>
221 this->Register<ComponentTypeT>(_type, _compDesc,
234 public:
template <
typename ComponentTypeT>
243 ComponentTypeT::typeId = typeHash;
244 ComponentTypeT::typeName = _type;
247 auto runtimeName =
typeid(ComponentTypeT).name();
248 auto runtimeNameIt = this->runtimeNamesById.
find(typeHash);
249 if (runtimeNameIt != this->runtimeNamesById.end())
254 if (runtimeNameIt->second != runtimeName)
257 <<
"Registered components of different types with same name: type ["
258 << runtimeNameIt->second <<
"] and type [" << runtimeName
259 <<
"] with name [" << _type <<
"]. Second type will not work."
270 if (debugEnv !=
"true")
273 if (debugEnv ==
"true")
275 std::cerr <<
"Environment variable [IGN_DEBUG_COMPONENT_FACTORY] "
276 <<
"is deprecated! Please use [GZ_DEBUG_COMPONENT_FACTORY]"
281 if (debugEnv ==
"true")
283 std::cout <<
"Registering [" << ComponentTypeT::typeName <<
"]"
288 this->compsById[ComponentTypeT::typeId].Add(_regObjId, _compDesc);
289 namesById[ComponentTypeT::typeId] = ComponentTypeT::typeName;
290 runtimeNamesById[ComponentTypeT::typeId] = runtimeName;
297 public:
template <
typename ComponentTypeT>
309 public:
template<
typename ComponentTypeT>
312 this->Unregister(ComponentTypeT::typeId, _regObjId);
339 auto it = this->compsById.find(_typeId);
340 if (it != this->compsById.end())
342 it->second.Remove(_regObjId);
344 if (it->second.Empty())
346 this->compsById.erase(it);
355 public:
template<
typename ComponentTypeT>
359 this->New(ComponentTypeT::typeId).release()));
371 auto it = this->compsById.find(_type);
372 if (it != this->compsById.end())
374 comp = it->second.Create();
390 if (
nullptr == _data)
392 gzerr <<
"Requested to create a new component instance with null "
395 else if (_type != _data->
TypeId())
397 gzerr <<
"The typeID of _type [" << _type <<
"] does not match the "
402 auto it = this->compsById.find(_type);
403 if (it != this->compsById.end())
405 comp = it->second.Create(_data);
419 for (
const auto &comp : this->compsById)
429 return this->compsById.find(_typeId) != this->compsById.end();
436 if (this->namesById.find(_typeId) != this->namesById.end())
437 return namesById.
at(_typeId);
462 #define GZ_SIM_REGISTER_COMPONENT(_compType, _classname) \
463 class GzSimComponents##_classname \
465 public: GzSimComponents##_classname() \
468 using Desc = sim::components::ComponentDescriptor<_classname>; \
469 sim::components::Factory::Instance()->Register<_classname>(\
470 _compType, new Desc(), sim::components::RegistrationObjectId(this));\
472 public: GzSimComponents##_classname( \
473 const GzSimComponents##_classname&) = delete; \
474 public: GzSimComponents##_classname( \
475 GzSimComponents##_classname&) = delete; \
476 public: ~GzSimComponents##_classname() \
478 using namespace gz; \
479 sim::components::Factory::Instance()->Unregister<_classname>( \
480 sim::components::RegistrationObjectId(this)); \
483 static GzSimComponents##_classname\
484 GzSimComponentsInitializer##_classname;