Main MRPT website > C++ reference for 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
45 {
46 namespace rtti
47 {
48 using TClassnameToRuntimeId = std::map<std::string, const TRuntimeClassId*>;
49 
50 /** A singleton with the central registry for CSerializable run-time classes:
51  * users do not use this class in any direct way.
52  * \note Class is thread-safe.
53  */
55 {
56  public:
57  /** The unique access point point to the singleton instance.
58  */
60  {
61  static CClassRegistry obj;
62  return obj;
63  }
64 
65  void Add(const std::string& className, const TRuntimeClassId& id)
66  {
67  m_being_modified = true;
68  {
69  std::unique_lock<std::mutex> lk(m_cs);
70 
71  // Sanity check: don't allow registering twice the same class name!
72  const auto it = registeredClasses.find(className);
73  if (it != registeredClasses.cend())
74  {
75  if (it->second != &id)
76  {
77  std::cerr << mrpt::format(
78  "[MRPT class registry] Warning: overwriting already "
79  "registered className=`%s` with different "
80  "`TRuntimeClassId`!\n",
81  className.c_str());
82  }
83  }
84  registeredClasses[className] = &id;
85  }
86  m_being_modified = false;
87  }
88 
89  const TRuntimeClassId* Get(const std::string& className)
90  {
91  // Optimization to avoid the costly lock() in virtually all situations:
92  bool has_to_unlock = false;
93  if (m_being_modified)
94  {
95  m_cs.lock();
96  has_to_unlock = true;
97  }
98  const TRuntimeClassId* ret = registeredClasses[className];
99  if (has_to_unlock) m_cs.unlock();
100  return ret;
101  }
102 
103  std::vector<const TRuntimeClassId*> getListOfAllRegisteredClasses()
104  {
105  std::unique_lock<std::mutex> lk(m_cs);
106 
107  std::vector<const TRuntimeClassId*> ret;
108  for (TClassnameToRuntimeId::iterator it = registeredClasses.begin();
109  it != registeredClasses.end(); ++it)
110  ret.push_back(it->second);
111  return ret;
112  }
113 
114  private:
115  // PRIVATE constructor
116  CClassRegistry() : m_being_modified(false) {}
117  // PRIVATE destructor
119  // This must be static since we can be called from C startup
120  // functions and it cannot be assured that classesKeeper will be
121  // initialized before other classes that call it...
123  std::mutex m_cs;
124  std::atomic<bool> m_being_modified;
125 };
126 
127 } // End of namespace
128 } // End of namespace
129 
130 /** Register all pending classes - to be called just before de-serializing an
131  * object, for example.
132 */
134 {
135  if (!pending_class_registers_modified) return; // Quick return
136 
137  while (pending_class_registers_count() != 0)
138  {
139  TRegisterFunction ptrToPtr = nullptr;
140  pending_class_registers().get(ptrToPtr);
142 
143  // Call it:
144  if (ptrToPtr != nullptr)
145  {
146  (*ptrToPtr)();
147  }
148  }
150 }
151 
152 /*---------------------------------------------------------------
153  RegisterClass
154  ---------------------------------------------------------------*/
156 {
157  // Register it:
159  std::string(pNewClass->className), *pNewClass);
160 
161  // Automatically register all classes when the first one is registered.
163 }
164 
165 /** For internal use within mrpt sources, and only in exceptional cases
166  * (CMultiMetricMaps, CImage,...)
167  */
169  const char* customName, const TRuntimeClassId* pNewClass)
170 {
171  // Register it:
172  CClassRegistry::Instance().Add(customName, *pNewClass);
173 
174  // Automatically register all classes when the first one is registered.
176 }
177 
178 std::vector<const TRuntimeClassId*> mrpt::rtti::getAllRegisteredClasses()
179 {
181 }
182 
183 std::vector<const TRuntimeClassId*>
185  const TRuntimeClassId* parent_id)
186 {
187  std::vector<const TRuntimeClassId*> res;
188  const auto lst = mrpt::rtti::getAllRegisteredClasses();
189  for (const auto& c : lst)
190  {
191  if (c->derivedFrom(parent_id) && c != parent_id)
192  {
193  res.push_back(c);
194  }
195  }
196  return res;
197 }
198 
199 /*---------------------------------------------------------------
200  findRegisteredClass
201  ---------------------------------------------------------------*/
203  const std::string& className)
204 {
205  return CClassRegistry::Instance().Get(className);
206 }
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
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
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().
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
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: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: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019