MRPT  1.9.9
internal_class_registry.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "rtti-precomp.h" // Precompiled headers
11 
12 #include <mrpt/rtti/CObject.h>
13 
14 #include <atomic>
15 #include <cstdarg>
16 #include <iostream>
17 #include <map>
18 #include <mutex>
19 
21 
22 using namespace mrpt::rtti;
23 
24 /*---------------------------------------------------------------
25  STATIC GLOBAL VARIABLES
26  ---------------------------------------------------------------*/
28 
29 // Creation on first call pattern:
31 {
32  static std::atomic<int> cnt(0);
33  return cnt;
34 }
35 
36 // Creation on first call pattern:
38 {
40  static queue_register_functions_t lst;
41  return lst;
42 }
43 
44 namespace mrpt::rtti
45 {
46 using TClassnameToRuntimeId = std::map<std::string, const TRuntimeClassId*>;
47 
48 /** A singleton with the central registry for CSerializable run-time classes:
49  * users do not use this class in any direct way.
50  * \note Class is thread-safe.
51  */
53 {
54  public:
55  /** The unique access point point to the singleton instance.
56  */
58  {
59  static CClassRegistry obj;
60  return obj;
61  }
62 
63  void Add(const std::string& className, const TRuntimeClassId& id)
64  {
65  m_being_modified = true;
66  {
67  std::unique_lock<std::mutex> lk(m_cs);
68 
69  // Sanity check: don't allow registering twice the same class name!
70  const auto it = registeredClasses.find(className);
71  if (it != registeredClasses.cend())
72  {
73  if (it->second != &id)
74  {
75  std::cerr << mrpt::format(
76  "[MRPT class registry] Warning: overwriting already "
77  "registered className=`%s` with different "
78  "`TRuntimeClassId`!\n",
79  className.c_str());
80  }
81  }
82  registeredClasses[className] = &id;
83  }
84  m_being_modified = false;
85  }
86 
87  const TRuntimeClassId* Get(const std::string& className)
88  {
89  // Optimization to avoid the costly lock() in virtually all situations:
90  bool has_to_unlock = false;
91  if (m_being_modified)
92  {
93  m_cs.lock();
94  has_to_unlock = true;
95  }
96  const TRuntimeClassId* ret = registeredClasses[className];
97  if (has_to_unlock) m_cs.unlock();
98  return ret;
99  }
100 
101  std::vector<const TRuntimeClassId*> getListOfAllRegisteredClasses()
102  {
103  std::unique_lock<std::mutex> lk(m_cs);
104 
105  std::vector<const TRuntimeClassId*> ret;
106  for (auto& registeredClasse : registeredClasses)
107  ret.push_back(registeredClasse.second);
108  return ret;
109  }
110 
111  private:
112  // This must be static since we can be called from C startup
113  // functions and it cannot be assured that classesKeeper will be
114  // initialized before other classes that call it...
116  std::mutex m_cs;
117  std::atomic<bool> m_being_modified{false};
118 };
119 
120 } // namespace mrpt::rtti
121 
122 /** Register all pending classes - to be called just before de-serializing an
123  * object, for example.
124  */
126 {
127  if (!pending_class_registers_modified) return; // Quick return
128 
129  while (pending_class_registers_count() != 0)
130  {
131  TRegisterFunction ptrToPtr = nullptr;
132  pending_class_registers().get(ptrToPtr);
134 
135  // Call it:
136  if (ptrToPtr != nullptr)
137  {
138  (*ptrToPtr)();
139  }
140  }
142 }
143 
144 /*---------------------------------------------------------------
145  RegisterClass
146  ---------------------------------------------------------------*/
148 {
149  // Register it:
150  if (pNewClass && pNewClass->className)
151  {
153  std::string(pNewClass->className), *pNewClass);
154  }
155  else
156  {
157  fprintf(
158  stderr,
159  "[mrpt::rtti::registerClass] Warning: Invoked with a nullptr "
160  "classname (?).\n");
161  }
162 
163  // Automatically register all classes when the first one is registered.
165 }
166 
167 /** For internal use within mrpt sources, and only in exceptional cases
168  * (CMultiMetricMaps, CImage,...)
169  */
171  const char* customName, const TRuntimeClassId* pNewClass)
172 {
173  // Register it:
174  CClassRegistry::Instance().Add(customName, *pNewClass);
175 
176  // Automatically register all classes when the first one is registered.
178 }
179 
180 std::vector<const TRuntimeClassId*> mrpt::rtti::getAllRegisteredClasses()
181 {
183 }
184 
185 std::vector<const TRuntimeClassId*>
187  const TRuntimeClassId* parent_id)
188 {
189  std::vector<const TRuntimeClassId*> res;
190  const auto lst = mrpt::rtti::getAllRegisteredClasses();
191  for (const auto& c : lst)
192  {
193  if (c->derivedFrom(parent_id) && c != parent_id)
194  {
195  res.push_back(c);
196  }
197  }
198  return res;
199 }
200 
201 /*---------------------------------------------------------------
202  findRegisteredClass
203  ---------------------------------------------------------------*/
205  const std::string& className)
206 {
207  return CClassRegistry::Instance().Get(className);
208 }
void registerAllPendingClasses()
Register all pending classes - to be called just before de-serializing an object, for example...
std::vector< const TRuntimeClassId * > getListOfAllRegisteredClasses()
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
std::vector< const TRuntimeClassId * > getAllRegisteredClassesChildrenOf(const TRuntimeClassId *parent_id)
Like getAllRegisteredClasses(), but filters the list to only include children clases of a given base ...
TClassnameToRuntimeId registeredClasses
A structure that holds runtime class type information.
Definition: CObject.h:31
bool get(TRegisterFunction &ret)
Retrieve the next message in the queue, or nullptr if there is no message.
GLsizei GLsizei GLuint * obj
Definition: glext.h:4085
const TRuntimeClassId * Get(const std::string &className)
const char * className
Definition: CObject.h:34
const GLubyte * c
Definition: glext.h:6406
GLsizei const GLchar ** string
Definition: glext.h:4116
void registerClassCustomName(const char *customName, const TRuntimeClassId *pNewClass)
Mostly for internal use within mrpt sources, to handle exceptional cases with multiple serialization ...
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:410
const TRuntimeClassId * findRegisteredClass(const std::string &className)
Return info about a given class by its name, or nullptr if the class is not registered.
bool pending_class_registers_modified
Set to true if pending_class_registers() has been called after registerAllPendingClasses().
A singleton with the central registry for CSerializable run-time classes: users do not use this class...
std::map< std::string, const TRuntimeClassId * > TClassnameToRuntimeId
GLuint id
Definition: glext.h:3920
std::atomic< int > & pending_class_registers_count()
static CClassRegistry & Instance()
The unique access point point to the singleton instance.
void(*)() TRegisterFunction
void registerClass(const mrpt::rtti::TRuntimeClassId *pNewClass)
Register a class into the MRPT internal list of "CObject" descendents.
void Add(const std::string &className, const TRuntimeClassId &id)
GLuint res
Definition: glext.h:7385
std::vector< const mrpt::rtti::TRuntimeClassId * > getAllRegisteredClasses()
Returns a list with all the classes registered in the system through mrpt::rtti::registerClass.
queue_register_functions_t & pending_class_registers()



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 928d0abbd Sun Oct 13 02:28:49 2019 +0200 at dom oct 13 02:30:11 CEST 2019