MRPT  1.9.9
internal_class_registry.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "rtti-precomp.h" // Precompiled headers
11 
12 #include <mrpt/rtti/CObject.h>
13 
14 #include <map>
15 #include <cstdarg>
16 #include <mutex>
17 #include <atomic>
18 #include <iostream>
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;
107  it != registeredClasses.end(); ++it)
108  ret.push_back(it->second);
109  return ret;
110  }
111 
112  private:
113  // PRIVATE constructor
115  // PRIVATE destructor
117  // This must be static since we can be called from C startup
118  // functions and it cannot be assured that classesKeeper will be
119  // initialized before other classes that call it...
121  std::mutex m_cs;
122  std::atomic<bool> m_being_modified;
123 };
124 
125 } // namespace mrpt::rtti
126 
127 /** Register all pending classes - to be called just before de-serializing an
128  * object, for example.
129 */
131 {
132  if (!pending_class_registers_modified) return; // Quick return
133 
134  while (pending_class_registers_count() != 0)
135  {
136  TRegisterFunction ptrToPtr = nullptr;
137  pending_class_registers().get(ptrToPtr);
139 
140  // Call it:
141  if (ptrToPtr != nullptr)
142  {
143  (*ptrToPtr)();
144  }
145  }
147 }
148 
149 /*---------------------------------------------------------------
150  RegisterClass
151  ---------------------------------------------------------------*/
153 {
154  // Register it:
156  std::string(pNewClass->className), *pNewClass);
157 
158  // Automatically register all classes when the first one is registered.
160 }
161 
162 /** For internal use within mrpt sources, and only in exceptional cases
163  * (CMultiMetricMaps, CImage,...)
164  */
166  const char* customName, const TRuntimeClassId* pNewClass)
167 {
168  // Register it:
169  CClassRegistry::Instance().Add(customName, *pNewClass);
170 
171  // Automatically register all classes when the first one is registered.
173 }
174 
175 std::vector<const TRuntimeClassId*> mrpt::rtti::getAllRegisteredClasses()
176 {
178 }
179 
180 std::vector<const TRuntimeClassId*>
182  const TRuntimeClassId* parent_id)
183 {
184  std::vector<const TRuntimeClassId*> res;
185  const auto lst = mrpt::rtti::getAllRegisteredClasses();
186  for (const auto& c : lst)
187  {
188  if (c->derivedFrom(parent_id) && c != parent_id)
189  {
190  res.push_back(c);
191  }
192  }
193  return res;
194 }
195 
196 /*---------------------------------------------------------------
197  findRegisteredClass
198  ---------------------------------------------------------------*/
200  const std::string& className)
201 {
202  return CClassRegistry::Instance().Get(className);
203 }
void registerAllPendingClasses()
Register all pending classes - to be called just before de-serializing an object, for example...
Scalar * iterator
Definition: eigen_plugins.h:26
std::vector< const TRuntimeClassId * > getListOfAllRegisteredClasses()
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:30
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:4070
const TRuntimeClassId * Get(const std::string &className)
const char * className
Definition: CObject.h:33
const GLubyte * c
Definition: glext.h:6313
GLsizei const GLchar ** string
Definition: glext.h:4101
void registerClassCustomName(const char *customName, const TRuntimeClassId *pNewClass)
Mostly for internal use within mrpt sources, to handle exceptional cases with multiple serialization ...
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::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
std::map< std::string, const TRuntimeClassId * > TClassnameToRuntimeId
GLuint id
Definition: glext.h:3909
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:7268
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: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020