Panda3D
typeRegistry.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file typeRegistry.cxx
10  * @author drose
11  * @date 2001-08-06
12  */
13 
14 #include "typeRegistry.h"
15 #include "typeRegistryNode.h"
16 #include "typeHandle.h"
17 #include "typedObject.h"
18 #include "indent.h"
19 #include "numeric_types.h"
20 
21 #include <algorithm>
22 
23 using std::cerr;
24 using std::ostream;
25 using std::ostringstream;
26 using std::string;
27 
28 MutexImpl *TypeRegistry::_lock = nullptr;
29 TypeRegistry *TypeRegistry::_global_pointer = nullptr;
30 
31 /**
32  * Creates a new Type of the given name and assigns a unique value to the
33  * type_handle. All type names must be unique. If the type name has already
34  * been used, the supplied type_handle value must match the name's assigned
35  * type_handle or an error is triggered. Returns true if the name wasn't
36  * defined before, false if it was.
37  */
38 bool TypeRegistry::
39 register_type(TypeHandle &type_handle, const string &name) {
40  _lock->lock();
41 
42  if (type_handle != TypeHandle::none()) {
43  // Here's a type that was already registered. Just make sure everything's
44  // still kosher.
45  TypeRegistryNode *rnode = look_up(type_handle, nullptr);
46  if (&type_handle == &rnode->_ref) {
47  // No problem.
48  _lock->unlock();
49  assert(rnode->_name == name);
50  return false;
51  }
52  }
53 
54  NameRegistry::iterator ri;
55  ri = _name_registry.find(name);
56 
57  if (ri == _name_registry.end()) {
58  // The name was not already used; this is the first time this class has
59  // been defined.
60 
61  TypeHandle new_handle;
62  new_handle._index = (int)_handle_registry.size();
63 
64  TypeRegistryNode *rnode = new TypeRegistryNode(new_handle, name, type_handle);
65  _handle_registry.push_back(rnode);
66  _name_registry[name] = rnode;
67  _derivations_fresh = false;
68 
69  type_handle = new_handle;
70  _lock->unlock();
71  return true;
72  }
73  TypeRegistryNode *rnode = (*ri).second;
74  assert(rnode->_name == (*ri).first);
75  assert(rnode->_handle._index >= 0 &&
76  rnode->_handle._index < (int)_handle_registry.size());
77  assert(_handle_registry[rnode->_handle._index] == rnode);
78  assert(rnode->_handle._index != 0);
79 
80  // The name was previously used; make sure the type_handle matches.
81  if (&type_handle == &rnode->_ref) {
82  // Ok, this was just a repeated attempt to register the same type.
83 
84  if (type_handle == rnode->_handle) {
85  // No problem.
86  _lock->unlock();
87  return false;
88  }
89  // But wait--the type_handle has changed! We kept a reference to the
90  // static _type_handle member in the class that was passed in at the first
91  // call to register_type(), and we got the same reference passed in this
92  // time, but now it's different! Bad juju.
93  cerr << "Reregistering " << name << "\n";
94  type_handle = rnode->_handle;
95  _lock->unlock();
96  return false;
97  }
98 
99  if (type_handle != rnode->_handle) {
100  // Hmm, we seem to have a contradictory type registration!
101  cerr
102  << "Attempt to register type " << name << " more than once!\n";
103 
104  // This is invalid, but we'll allow it anyway. It seems to happen for
105  // some reason under GNU libc5 that we occasionally end up with two
106  // legitimate copies of the same class object in memory--each with its own
107  // static _type_handle member.
108 
109  type_handle = rnode->_handle;
110  }
111  _lock->unlock();
112  return false;
113 }
114 
115 /**
116  * Registers a new type on-the-fly, presumably at runtime. A new TypeHandle
117  * is returned if the typename was not seen before; otherwise the same
118  * TypeHandle that was last used for this typename is returned.
119  */
121 register_dynamic_type(const string &name) {
122  _lock->lock();
123 
124  NameRegistry::iterator ri;
125  ri = _name_registry.find(name);
126 
127  if (ri == _name_registry.end()) {
128  // The name was not already used; this is the first time this class has
129  // been defined.
130 
131  // We must dynamically allocate a new handle so the TypeRegistryNode has
132  // something unique to point to. This doesn't really mean anything,
133  // though.
134  TypeHandle *new_handle = new TypeHandle;
135  new_handle->_index = (int)_handle_registry.size();
136 
137  TypeRegistryNode *rnode = new TypeRegistryNode(*new_handle, name, *new_handle);
138  _handle_registry.push_back(rnode);
139  _name_registry[name] = rnode;
140  _derivations_fresh = false;
141 
142  _lock->unlock();
143  return *new_handle;
144  }
145 
146  // Return the TypeHandle previously obtained.
147  TypeRegistryNode *rnode = (*ri).second;
148  TypeHandle handle = rnode->_handle;
149  _lock->unlock();
150  return handle;
151 }
152 
153 /**
154  * Records that the type referenced by child inherits directly from the type
155  * referenced by parent. In the event of multiple inheritance, this should be
156  * called once for each parent class.
157  */
158 void TypeRegistry::
160  _lock->lock();
161 
162  TypeRegistryNode *cnode = look_up(child, nullptr);
163  assert(cnode != nullptr);
164  TypeRegistryNode *pnode = look_up(parent, nullptr);
165  assert(pnode != nullptr);
166 
167  // First, we'll just run through the list to make sure we hadn't already
168  // made this connection.
169  TypeRegistryNode::Classes::iterator ni;
170  ni = find(cnode->_parent_classes.begin(), cnode->_parent_classes.end(),
171  pnode);
172 
173  if (ni == cnode->_parent_classes.end()) {
174  cnode->_parent_classes.push_back(pnode);
175  pnode->_child_classes.push_back(cnode);
176  _derivations_fresh = false;
177  }
178 
179  _lock->unlock();
180 }
181 
182 /**
183  * Indicates an alternate name for the same type. This is particularly useful
184  * when a type has changed names, since the type is stored in a Bam file by
185  * name; setting the original name as the alternate will allow the type to be
186  * correctly read from old Bam files.
187  */
188 void TypeRegistry::
189 record_alternate_name(TypeHandle type, const string &name) {
190  _lock->lock();
191 
192  TypeRegistryNode *rnode = look_up(type, nullptr);
193  if (rnode != nullptr) {
194  NameRegistry::iterator ri =
195  _name_registry.insert(NameRegistry::value_type(name, rnode)).first;
196 
197  if ((*ri).second != rnode) {
198  _lock->unlock();
199  cerr
200  << "Name " << name << " already assigned to TypeHandle "
201  << rnode->_name << "; cannot reassign to " << type << "\n";
202  return;
203  }
204 
205  }
206 
207  _lock->unlock();
208 }
209 
210 #ifdef HAVE_PYTHON
211 /**
212  * Records the given Python type pointer in the type registry for the benefit
213  * of interrogate, which expects this to contain a Dtool_PyTypedObject.
214  */
215 void TypeRegistry::
216 record_python_type(TypeHandle type, PyObject *python_type) {
217  _lock->lock();
218 
219  TypeRegistryNode *rnode = look_up(type, nullptr);
220  if (rnode != nullptr) {
221  rnode->_python_type = python_type;
222  }
223 
224  _lock->unlock();
225 }
226 #endif
227 
228 /**
229  * Looks for a previously-registered type of the given name. Returns its
230  * TypeHandle if it exists, or TypeHandle::none() if there is no such type.
231  */
233 find_type(const string &name) const {
234  _lock->lock();
235 
236  TypeHandle handle = TypeHandle::none();
237  NameRegistry::const_iterator ri;
238  ri = _name_registry.find(name);
239  if (ri != _name_registry.end()) {
240  handle = (*ri).second->_handle;
241  }
242  _lock->unlock();
243 
244  return handle;
245 }
246 
247 /**
248  * Looks for a previously-registered type with the given id number (as
249  * returned by TypeHandle::get_index()). Returns its TypeHandle if it exists,
250  * or TypeHandle::none() if there is no such type.
251  */
253 find_type_by_id(int id) const {
254  if (id < 0 ||id >= (int)_handle_registry.size()) {
255  cerr
256  << "Invalid TypeHandle index " << id
257  << "! Is memory corrupt?\n";
258  return TypeHandle::none();
259  }
260 
261  return _handle_registry[id]->_handle;
262 }
263 
264 
265 /**
266  * Returns the name of the indicated type.
267  *
268  * The "object" pointer is an optional pointer to the TypedObject class that
269  * owns this TypeHandle. It is only used in case the TypeHandle is
270  * inadvertantly undefined.
271  */
272 string TypeRegistry::
273 get_name(TypeHandle type, TypedObject *object) const {
274  _lock->lock();
275  TypeRegistryNode *rnode = look_up(type, object);
276  assert(rnode != nullptr);
277  string name = rnode->_name;
278  _lock->unlock();
279 
280  return name;
281 }
282 
283 /**
284  * Returns true if the first type is derived from the second type, false
285  * otherwise.
286  *
287  * The "child_object" pointer is an optional pointer to the TypedObject class
288  * that owns the child TypeHandle. It is only used in case the TypeHandle is
289  * inadvertently undefined.
290  *
291  * This function definition follows the definitions for look_up() and
292  * freshen_derivations() just to maximize the chance the the compiler will be
293  * able to inline the above functions. Yeah, a compiler shouldn't care, but
294  * there's a big different between "shouldn't" and "doesn't".
295  */
296 bool TypeRegistry::
298  TypedObject *child_object) {
299  _lock->lock();
300 
301  const TypeRegistryNode *child_node = look_up(child, child_object);
302  const TypeRegistryNode *base_node = look_up(base, nullptr);
303 
304  assert(child_node != nullptr);
305  assert(base_node != nullptr);
306 
307  freshen_derivations();
308 
309  bool result = TypeRegistryNode::is_derived_from(child_node, base_node);
310  _lock->unlock();
311  return result;
312 }
313 
314 /**
315  * Returns the total number of unique TypeHandles in the system.
316  */
317 int TypeRegistry::
319  _lock->lock();
320  int num_types = (int)_handle_registry.size();
321  _lock->unlock();
322  return num_types;
323 }
324 
325 /**
326  * Returns the nth TypeHandle in the system. See get_num_typehandles().
327  */
329 get_typehandle(int n) {
330  _lock->lock();
331  TypeRegistryNode *rnode = nullptr;
332  if (n >= 0 && n < (int)_handle_registry.size()) {
333  rnode = _handle_registry[n];
334  }
335  _lock->unlock();
336 
337  if (rnode != nullptr) {
338  return rnode->_handle;
339  }
340 
341  return TypeHandle::none();
342 }
343 
344 /**
345  * Returns the number of root classes--that is, classes that do not inherit
346  * from any other classes--known in the system.
347  */
348 int TypeRegistry::
350  _lock->lock();
351  freshen_derivations();
352  int num_roots = (int)_root_classes.size();
353  _lock->unlock();
354  return num_roots;
355 }
356 
357 /**
358  * Returns the nth root class in the system. See get_num_root_classes().
359  */
361 get_root_class(int n) {
362  _lock->lock();
363  freshen_derivations();
364  TypeHandle handle;
365  if (n >= 0 && n < (int)_root_classes.size()) {
366  handle = _root_classes[n]->_handle;
367  } else {
368  handle = TypeHandle::none();
369  }
370  _lock->unlock();
371 
372  return handle;
373 }
374 
375 /**
376  * Returns the number of parent classes that the indicated type is known to
377  * have. This may then be used to index into get_parent_class(). The result
378  * will be 0 if this class does not inherit from any other classes, 1 if
379  * normal, single inheritance is in effect, or greater than one if multiple
380  * inheritance is in effect.
381  *
382  * The "object" pointer is an optional pointer to the TypedObject class that
383  * owns this TypeHandle. It is only used in case the TypeHandle is
384  * inadvertantly undefined.
385  */
386 int TypeRegistry::
387 get_num_parent_classes(TypeHandle child, TypedObject *child_object) const {
388  _lock->lock();
389  TypeRegistryNode *rnode = look_up(child, child_object);
390  assert(rnode != nullptr);
391  int num_parents = (int)rnode->_parent_classes.size();
392  _lock->unlock();
393  return num_parents;
394 }
395 
396 /**
397  * Returns the nth parent class of this type. The index should be in the
398  * range 0 <= index < get_num_parent_classes().
399  */
401 get_parent_class(TypeHandle child, int index) const {
402  _lock->lock();
403  TypeHandle handle;
404  TypeRegistryNode *rnode = look_up(child, nullptr);
405  assert(rnode != nullptr);
406  if (index >= 0 && index < (int)rnode->_parent_classes.size()) {
407  handle = rnode->_parent_classes[index]->_handle;
408  } else {
409  handle = TypeHandle::none();
410  }
411  _lock->unlock();
412  return handle;
413 }
414 
415 /**
416  * Returns the number of child classes that the indicated type is known to
417  * have. This may then be used to index into get_child_class().
418  *
419  * The "object" pointer is an optional pointer to the TypedObject class that
420  * owns this TypeHandle. It is only used in case the TypeHandle is
421  * inadvertantly undefined.
422  */
423 int TypeRegistry::
424 get_num_child_classes(TypeHandle child, TypedObject *child_object) const {
425  _lock->lock();
426  TypeRegistryNode *rnode = look_up(child, child_object);
427  assert(rnode != nullptr);
428  int num_children = (int)rnode->_child_classes.size();
429  _lock->unlock();
430  return num_children;
431 }
432 
433 /**
434  * Returns the nth child class of this type. The index should be in the range
435  * 0 <= index < get_num_child_classes().
436  */
438 get_child_class(TypeHandle child, int index) const {
439  _lock->lock();
440  TypeHandle handle;
441  TypeRegistryNode *rnode = look_up(child, nullptr);
442  assert(rnode != nullptr);
443  if (index >= 0 && index < (int)rnode->_child_classes.size()) {
444  handle = rnode->_child_classes[index]->_handle;
445  } else {
446  handle = TypeHandle::none();
447  }
448  _lock->unlock();
449  return handle;
450 }
451 
452 /**
453  * Returns the parent of the indicated child class that is in a direct line of
454  * inheritance to the indicated ancestor class. This is useful in the
455  * presence of multiple inheritance to try to determine what properties an
456  * unknown type may have.
457  *
458  * The "object" pointer is an optional pointer to the TypedObject class that
459  * owns this TypeHandle. It is only used in case the TypeHandle is
460  * inadvertantly undefined.
461  */
464  TypedObject *child_object) {
465  _lock->lock();
466  TypeHandle handle;
467  const TypeRegistryNode *child_node = look_up(child, child_object);
468  const TypeRegistryNode *base_node = look_up(base, nullptr);
469  assert(child_node != nullptr &&
470  base_node != nullptr);
471  freshen_derivations();
472  handle = TypeRegistryNode::get_parent_towards(child_node, base_node);
473  _lock->unlock();
474  return handle;
475 }
476 
477 
478 /**
479  * Walks through the TypeRegistry tree and makes sure that each type that was
480  * previously registered is *still* registered. This seems to get broken in
481  * certain circumstances when compiled against libc5--it is as if the static
482  * initializer stomps on the _type_handle values of each class after they've
483  * been registered.
484  */
485 void TypeRegistry::
487  init_lock();
488  _lock->lock();
489  HandleRegistry::iterator ri;
490  TypeRegistry *reg = ptr();
491  for (ri = reg->_handle_registry.begin();
492  ri != reg->_handle_registry.end();
493  ++ri) {
494  TypeRegistryNode *rnode = (*ri);
495  if (rnode != nullptr && rnode->_handle != rnode->_ref) {
496  cerr << "Reregistering " << rnode->_name << "\n";
497  }
498  }
499  _lock->unlock();
500 }
501 
502 
503 /**
504  * Makes an attempt to format the entire TypeRegistry in a nice way that shows
505  * the derivation tree as intelligently as possible.
506  */
507 void TypeRegistry::
508 write(ostream &out) const {
509  _lock->lock();
510  do_write(out);
511  _lock->unlock();
512 }
513 
514 /**
515  *
516  */
517 TypeRegistry::
518 TypeRegistry() {
519  // We'll start out our handle_registry with a default entry for the
520  // TypeHandles whose index number is zero, and are therefore (probably)
521  // uninitialized.
522  _handle_registry.push_back(nullptr);
523 
524  _derivations_fresh = false;
525 
526  // Here's a few sanity checks on the sizes of our words. We have to put it
527  // here, at runtime, since there doesn't appear to be a cross-platform
528  // compile-time way to verify that we've chosen the right word sizes.
529  assert(sizeof(uint8_t) == 1 && sizeof(int8_t) == 1);
530  assert(sizeof(uint16_t) == 2 && sizeof(int16_t) == 2);
531  assert(sizeof(uint32_t) == 4 && sizeof(int32_t) == 4);
532  assert(sizeof(uint64_t) == 8 && sizeof(int64_t) == 8);
533 
534  assert(sizeof(PN_float32) == 4);
535  assert(sizeof(PN_float64) == 8);
536 }
537 
538 /**
539  * Constructs the TypeRegistry object for the first time.
540  */
541 void TypeRegistry::
542 init_global_pointer() {
543  init_lock();
545  _global_pointer = new TypeRegistry;
546 }
547 
548 /**
549  * Rebuilds the derivation data structures after some derivation relationship
550  * has been modified, so that class relationships can quickly be determined.
551  */
552 void TypeRegistry::
553 rebuild_derivations() {
554  // First, remove all of the old data from the last type
555  // rebuild_derivations() was called.
556  _root_classes.clear();
557 
558  HandleRegistry::iterator hi;
559  for (hi = _handle_registry.begin();
560  hi != _handle_registry.end();
561  ++hi) {
562  TypeRegistryNode *node = *hi;
563  if (node != nullptr) {
564  node->clear_subtree();
565  }
566  }
567 
568  // Start by getting the list of root classes: those classes which do not
569  // derive from anything.
570  for (hi = _handle_registry.begin();
571  hi != _handle_registry.end();
572  ++hi) {
573  TypeRegistryNode *node = *hi;
574  if (node != nullptr && node->_parent_classes.empty()) {
575  _root_classes.push_back(node);
576 
577  // Also, for each root class, define a subtree.
578  node->define_subtree();
579  }
580  }
581 }
582 
583 /**
584  * The private implementation of write(), this assumes the lock is already
585  * held.
586  */
587 void TypeRegistry::
588 do_write(ostream &out) const {
589  // Recursively write out the tree, starting from each node that has no
590  // parent.
591  HandleRegistry::const_iterator hi;
592  for (hi = _handle_registry.begin();
593  hi != _handle_registry.end();
594  ++hi) {
595  const TypeRegistryNode *root = *hi;
596  if (root != nullptr && root->_parent_classes.empty()) {
597  write_node(out, 2, root);
598  }
599  }
600 }
601 
602 /**
603  * Writes a single TypeRegistryNode out, along with all of its descendants.
604  * Assumes the lock is already held.
605  */
606 void TypeRegistry::
607 write_node(ostream &out, int indent_level, const TypeRegistryNode *node) const {
608  indent(out, indent_level) << node->_handle.get_index() << " " << node->_name;
609  if (!node->_parent_classes.empty()) {
610  out << " : " << node->_parent_classes[0]->_name;
611  for (int pi = 1; pi < (int)node->_parent_classes.size(); pi++) {
612  out << ", " << node->_parent_classes[pi]->_name;
613  }
614  }
615  out << "\n";
616 
617  for (int i = 0; i < (int)node->_child_classes.size(); i++) {
618  write_node(out, indent_level + 2, node->_child_classes[i]);
619  }
620 }
621 
622 /**
623  * Called by look_up when it detects an invalid TypeHandle pointer. In non-
624  * release builds, this method will do what it can to recover from this and
625  * initialize the type anyway.
626  *
627  * Assumes the lock is already held.
628  */
629 TypeRegistryNode *TypeRegistry::
630 look_up_invalid(TypeHandle handle, TypedObject *object) const {
631 #ifndef NDEBUG
632  if (handle._index == 0) {
633  // The TypeHandle is unregistered. This is an error condition.
634 
635  if (object != nullptr) {
636  // But we're lucky enough to have a TypedObject pointer handy! Maybe we
637  // can use it to resolve the error. We have to drop the lock while we
638  // do this, so we don't get a recursive lock.
639  _lock->unlock();
640  handle = object->force_init_type();
641  _lock->lock();
642 
643  if (handle._index == 0) {
644  // Strange.
645  cerr
646  << "Unable to force_init_type() on unregistered TypeHandle.\n";
647  return nullptr;
648  }
649 
650  // Now get the name for printing. We can't use TypeHandle:: get_name()
651  // since that recursively calls look_up().
652  ostringstream name;
653  if (handle._index > 0 && handle._index < (int)_handle_registry.size()) {
654  TypeRegistryNode *rnode = _handle_registry[handle._index];
655  if (rnode != nullptr) {
656  name << rnode->_name;
657  name << " (index " << handle._index << ")";
658  } else {
659  name << "NULL (index " << handle._index << ")";
660  }
661  } else {
662  name << "index " << handle._index;
663  }
664 
665  if (handle == object->get_type()) {
666  // Problem solved!
667  cerr
668  << "Type " << name.str() << " was unregistered!\n";
669  } else {
670  // No good; it looks like the TypeHandle belongs to a class that
671  // defined get_type(), but didn't define force_init_type().
672  cerr
673  << "Attempt to reference unregistered TypeHandle. Type is of some\n"
674  << "class derived from type " << name.str() << " that doesn't define\n"
675  << "a good force_init_type() method.\n";
676  return nullptr;
677  }
678 
679  } else {
680  // We don't have a TypedObject pointer, so there's nothing we can do
681  // about it.
682  cerr
683  << "Attempt to reference unregistered TypeHandle!\n"
684  << "Registered TypeHandles are:\n";
685  do_write(cerr);
686  return nullptr;
687  }
688  }
689 
690  if (handle._index < 0 ||
691  handle._index >= (int)_handle_registry.size()) {
692  cerr
693  << "Invalid TypeHandle index " << handle._index
694  << "! Is memory corrupt?\n";
695  return nullptr;
696  }
697 #endif // NDEBUG
698 
699  return _handle_registry[handle._index];
700 }
701 
702 /**
703 
704  */
705 extern "C" int
706 get_best_parent_from_Set(int id, const std::set<int> &this_set) {
707  // most common case..
708  if (this_set.find(id) != this_set.end()) {
709  return id;
710  }
711 
713  if (th == TypeHandle::none()) {
714  return -1;
715  }
716 
717  return th.get_best_parent_from_Set(this_set);
718 }
TypeRegistry::is_derived_from
bool is_derived_from(TypeHandle child, TypeHandle base, TypedObject *child_object)
Returns true if the first type is derived from the second type, false otherwise.
Definition: typeRegistry.cxx:297
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
TypeRegistry::register_dynamic_type
TypeHandle register_dynamic_type(const std::string &name)
Registers a new type on-the-fly, presumably at runtime.
Definition: typeRegistry.cxx:121
typeRegistryNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeRegistry::find_type
TypeHandle find_type(const std::string &name) const
Looks for a previously-registered type of the given name.
Definition: typeRegistry.cxx:233
TypeRegistry::record_alternate_name
void record_alternate_name(TypeHandle type, const std::string &name)
Indicates an alternate name for the same type.
Definition: typeRegistry.cxx:189
init_memory_hook
void init_memory_hook()
Any code that might need to use PANDA_MALLOC or PANDA_FREE, or any methods of the global memory_hook ...
Definition: dtoolbase.cxx:38
numeric_types.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle::get_index
get_index
Returns the integer index associated with this TypeHandle.
Definition: typeHandle.h:135
TypeRegistryNode::define_subtree
void define_subtree()
Indicates that this TypeRegistryNode is the top of a subtree within the inheritance graph (typically,...
Definition: typeRegistryNode.cxx:183
TypeRegistry::reregister_types
static void reregister_types()
Walks through the TypeRegistry tree and makes sure that each type that was previously registered is *...
Definition: typeRegistry.cxx:486
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypeRegistry::get_name
std::string get_name(TypeHandle type, TypedObject *object) const
Returns the name of the indicated type.
Definition: typeRegistry.cxx:273
typedObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeRegistry::write
void write(std::ostream &out) const
Makes an attempt to format the entire TypeRegistry in a nice way that shows the derivation tree as in...
Definition: typeRegistry.cxx:508
TypeRegistry::get_parent_towards
TypeHandle get_parent_towards(TypeHandle child, TypeHandle base, TypedObject *child_object)
Returns the parent of the indicated child class that is in a direct line of inheritance to the indica...
Definition: typeRegistry.cxx:463
TypeRegistry::get_child_class
TypeHandle get_child_class(TypeHandle child, int index) const
Returns the nth child class of this type.
Definition: typeRegistry.cxx:438
TypeRegistry::record_derivation
void record_derivation(TypeHandle child, TypeHandle parent)
Records that the type referenced by child inherits directly from the type referenced by parent.
Definition: typeRegistry.cxx:159
TypeRegistryNode::clear_subtree
void clear_subtree()
Removes any subtree definition previously set up via define_subtree(), in preparation for rebuilding ...
Definition: typeRegistryNode.cxx:171
TypeRegistry::register_type
bool register_type(TypeHandle &type_handle, const std::string &name)
Creates a new Type of the given name and assigns a unique value to the type_handle.
Definition: typeRegistry.cxx:39
TypeRegistryNode::get_parent_towards
static TypeHandle get_parent_towards(const TypeRegistryNode *child, const TypeRegistryNode *base)
Returns the first parent class of child that is a descendant of the indicated base class.
Definition: typeRegistryNode.cxx:148
MutexDummyImpl
A fake mutex implementation for single-threaded applications that don't need any synchronization cont...
Definition: mutexDummyImpl.h:24
TypeRegistry::get_parent_class
TypeHandle get_parent_class(TypeHandle child, int index) const
Returns the nth parent class of this type.
Definition: typeRegistry.cxx:401
TypeHandle::get_best_parent_from_Set
int get_best_parent_from_Set(const std::set< int > &legal_vals) const
Return the Index of the BEst fit Classs from a set.
Definition: typeHandle.cxx:175
TypeRegistry::ptr
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
Definition: typeRegistry.I:30
TypeRegistry::get_num_parent_classes
int get_num_parent_classes(TypeHandle child, TypedObject *child_object) const
Returns the number of parent classes that the indicated type is known to have.
Definition: typeRegistry.cxx:387
TypeRegistry::get_num_typehandles
get_num_typehandles
Returns the total number of unique TypeHandles in the system.
Definition: typeRegistry.h:61
TypeRegistryNode
This is a single entry in the TypeRegistry.
Definition: typeRegistryNode.h:30
TypeRegistry
The TypeRegistry class maintains all the assigned TypeHandles in a given system.
Definition: typeRegistry.h:36
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
typeRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeRegistry::get_num_root_classes
get_num_root_classes
Returns the number of root classes–that is, classes that do not inherit from any other classes–known ...
Definition: typeRegistry.h:65
TypeRegistry::get_root_class
get_root_class
Returns the nth root class in the system.
Definition: typeRegistry.h:65
TypeRegistry::find_type_by_id
TypeHandle find_type_by_id(int id) const
Looks for a previously-registered type with the given id number (as returned by TypeHandle::get_index...
Definition: typeRegistry.cxx:253
TypeRegistry::get_typehandle
get_typehandle
Returns the nth TypeHandle in the system.
Definition: typeRegistry.h:61
TypeRegistry::get_num_child_classes
int get_num_child_classes(TypeHandle child, TypedObject *child_object) const
Returns the number of child classes that the indicated type is known to have.
Definition: typeRegistry.cxx:424
TypeRegistryNode::is_derived_from
static bool is_derived_from(const TypeRegistryNode *child, const TypeRegistryNode *base)
Returns true if the child RegistryNode represents a class that inherits directly or indirectly from t...
Definition: typeRegistryNode.cxx:37
typeHandle.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedObject
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:88