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