Panda3D
 All Classes Functions Variables Enumerations
typeRegistry.cxx
00001 // Filename: typeRegistry.cxx
00002 // Created by:  drose (06Aug01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "typeRegistry.h"
00016 #include "typeRegistryNode.h"
00017 #include "typeHandle.h"
00018 #include "typedObject.h"
00019 #include "indent.h"
00020 #include "numeric_types.h"
00021 
00022 #include <algorithm>
00023 
00024 MutexImpl *TypeRegistry::_lock = NULL;
00025 TypeRegistry *TypeRegistry::_global_pointer = NULL;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: TypeRegistry::register_type
00029 //       Access: Public
00030 //  Description: Creates a new Type of the given name and assigns a
00031 //               unique value to the type_handle.  All type names must
00032 //               be unique.  If the type name has already been used,
00033 //               the supplied type_handle value must match the name's
00034 //               assigned type_handle or an error is triggered.
00035 //               Returns true if the name wasn't defined before, false
00036 //               if it was.
00037 ////////////////////////////////////////////////////////////////////
00038 bool TypeRegistry::
00039 register_type(TypeHandle &type_handle, const string &name) {
00040   _lock->acquire();
00041 
00042   if (type_handle != TypeHandle::none()) {
00043     // Here's a type that was already registered.  Just make sure
00044     // everything's still kosher.
00045     TypeRegistryNode *rnode = look_up(type_handle, NULL);
00046     if (&type_handle == &rnode->_ref) {
00047       // No problem.
00048       _lock->release();
00049       assert(rnode->_name == name);
00050       return false;
00051     }
00052   }
00053 
00054   NameRegistry::iterator ri;
00055   ri = _name_registry.find(name);
00056 
00057   if (ri == _name_registry.end()) {
00058     // The name was not already used; this is the first time this
00059     // class has been defined.
00060 
00061     TypeHandle new_handle;
00062     new_handle._index = _handle_registry.size();
00063 
00064     TypeRegistryNode *rnode = new TypeRegistryNode(new_handle, name, type_handle);
00065     _handle_registry.push_back(rnode);
00066     _name_registry[name] = rnode;
00067     _derivations_fresh = false;
00068 
00069     type_handle = new_handle;
00070     _lock->release();
00071     return true;
00072   }
00073   TypeRegistryNode *rnode = (*ri).second;
00074   assert(rnode->_name == (*ri).first);
00075   assert(rnode->_handle._index >= 0 &&
00076            rnode->_handle._index < (int)_handle_registry.size());
00077   assert(_handle_registry[rnode->_handle._index] == rnode);
00078   assert(rnode->_handle._index != 0);
00079 
00080   // The name was previously used; make sure the type_handle matches.
00081   if (&type_handle == &rnode->_ref) {
00082     // Ok, this was just a repeated attempt to register the same type.
00083 
00084     if (type_handle == rnode->_handle) {
00085       // No problem.
00086       _lock->release();
00087       return false;
00088     }
00089     // But wait--the type_handle has changed!  We kept a reference to
00090     // the static _type_handle member in the class that was passed in
00091     // at the first call to register_type(), and we got the same
00092     // reference passed in this time, but now it's different!  Bad
00093     // juju.
00094     cerr << "Reregistering " << name << "\n";
00095     type_handle == rnode->_handle;
00096     _lock->release();
00097     return false;
00098   }
00099 
00100   if (type_handle != rnode->_handle) {
00101     // Hmm, we seem to have a contradictory type registration!
00102     cerr
00103       << "Attempt to register type " << name << " more than once!\n";
00104 
00105     // This is invalid, but we'll allow it anyway.  It seems to happen
00106     // for some reason under GNU libc5 that we occasionally end up
00107     // with two legitimate copies of the same class object in
00108     // memory--each with its own static _type_handle member.
00109 
00110     type_handle = rnode->_handle;
00111   }
00112   _lock->release();
00113   return false;
00114 }
00115 
00116 ////////////////////////////////////////////////////////////////////
00117 //     Function: TypeRegistry::register_dynamic_type
00118 //       Access: Public
00119 //  Description: Registers a new type on-the-fly, presumably at
00120 //               runtime.  A new TypeHandle is returned if the
00121 //               typename was not seen before; otherwise the same
00122 //               TypeHandle that was last used for this typename is
00123 //               returned.
00124 ////////////////////////////////////////////////////////////////////
00125 TypeHandle TypeRegistry::
00126 register_dynamic_type(const string &name) {
00127   _lock->acquire();
00128 
00129   NameRegistry::iterator ri;
00130   ri = _name_registry.find(name);
00131 
00132   if (ri == _name_registry.end()) {
00133     // The name was not already used; this is the first time this
00134     // class has been defined.
00135 
00136     // We must dynamically allocate a new handle so the TypeRegistryNode
00137     // has something unique to point to.  This doesn't really mean
00138     // anything, though.
00139     TypeHandle *new_handle = new TypeHandle;
00140     new_handle->_index = _handle_registry.size();
00141 
00142     TypeRegistryNode *rnode = new TypeRegistryNode(*new_handle, name, *new_handle);
00143     _handle_registry.push_back(rnode);
00144     _name_registry[name] = rnode;
00145     _derivations_fresh = false;
00146 
00147     _lock->release();
00148     return *new_handle;
00149   }
00150 
00151   // Return the TypeHandle previously obtained.
00152   TypeRegistryNode *rnode = (*ri).second;
00153   TypeHandle handle = rnode->_handle;
00154   _lock->release();
00155   return handle;
00156 }
00157 
00158 ////////////////////////////////////////////////////////////////////
00159 //     Function: TypeRegistry::record_derivation
00160 //       Access: Public
00161 //  Description: Records that the type referenced by child inherits
00162 //               directly from the type referenced by parent.  In the
00163 //               event of multiple inheritance, this should be called
00164 //               once for each parent class.
00165 ////////////////////////////////////////////////////////////////////
00166 void TypeRegistry::
00167 record_derivation(TypeHandle child, TypeHandle parent) {
00168   _lock->acquire();
00169 
00170   TypeRegistryNode *cnode = look_up(child, NULL);
00171   assert(cnode != (TypeRegistryNode *)NULL);
00172   TypeRegistryNode *pnode = look_up(parent, NULL);
00173   assert(pnode != (TypeRegistryNode *)NULL);
00174 
00175   // First, we'll just run through the list to make sure we hadn't
00176   // already made this connection.
00177   TypeRegistryNode::Classes::iterator ni;
00178   ni = find(cnode->_parent_classes.begin(), cnode->_parent_classes.end(),
00179             pnode);
00180 
00181   if (ni == cnode->_parent_classes.end()) {
00182     cnode->_parent_classes.push_back(pnode);
00183     pnode->_child_classes.push_back(cnode);
00184     _derivations_fresh = false;
00185   }
00186 
00187   _lock->release();
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: TypeRegistry::record_alternate_name
00192 //       Access: Public
00193 //  Description: Indicates an alternate name for the same type.  This
00194 //               is particularly useful when a type has changed names,
00195 //               since the type is stored in a Bam file by name;
00196 //               setting the original name as the alternate will allow
00197 //               the type to be correctly read from old Bam files.
00198 ////////////////////////////////////////////////////////////////////
00199 void TypeRegistry::
00200 record_alternate_name(TypeHandle type, const string &name) {
00201   _lock->acquire();
00202 
00203   TypeRegistryNode *rnode = look_up(type, (TypedObject *)NULL);
00204   if (rnode != (TypeRegistryNode *)NULL) {
00205     NameRegistry::iterator ri =
00206       _name_registry.insert(NameRegistry::value_type(name, rnode)).first;
00207     if ((*ri).second != rnode) {
00208       cerr
00209         << "Name " << name << " already assigned to TypeHandle "
00210         << rnode->_name << "; cannot reassign to " << type << "\n";
00211     }
00212   }
00213 
00214   _lock->release();
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: TypeRegistry::find_type
00219 //       Access: Published
00220 //  Description: Looks for a previously-registered type of the given
00221 //               name.  Returns its TypeHandle if it exists, or
00222 //               TypeHandle::none() if there is no such type.
00223 ////////////////////////////////////////////////////////////////////
00224 TypeHandle TypeRegistry::
00225 find_type(const string &name) const {
00226   _lock->acquire();
00227 
00228   TypeHandle handle = TypeHandle::none();
00229   NameRegistry::const_iterator ri;
00230   ri = _name_registry.find(name);
00231   if (ri != _name_registry.end()) {
00232     handle = (*ri).second->_handle;
00233   }
00234   _lock->release();
00235 
00236   return handle;
00237 }
00238 
00239 ////////////////////////////////////////////////////////////////////
00240 //     Function: TypeRegistry::find_type_by_id
00241 //       Access: Published
00242 //  Description: Looks for a previously-registered type with the given
00243 //               id number (as returned by TypeHandle::get_index()).
00244 //               Returns its TypeHandle if it exists, or
00245 //               TypeHandle::none() if there is no such type.
00246 ///////////////////////////////////////////////////////////////////
00247 TypeHandle TypeRegistry::
00248 find_type_by_id(int id) const {
00249   if (id < 0 ||id >= (int)_handle_registry.size()) {
00250     cerr
00251       << "Invalid TypeHandle index " << id
00252       << "!  Is memory corrupt?\n";
00253     return TypeHandle::none();
00254   }
00255 
00256   return _handle_registry[id]->_handle;
00257 }
00258 
00259 
00260 ////////////////////////////////////////////////////////////////////
00261 //     Function: TypeRegistry::get_name
00262 //       Access: Published
00263 //  Description: Returns the name of the indicated type.
00264 //
00265 //               The "object" pointer is an optional pointer to the
00266 //               TypedObject class that owns this TypeHandle.  It is
00267 //               only used in case the TypeHandle is inadvertantly
00268 //               undefined.
00269 ////////////////////////////////////////////////////////////////////
00270 string TypeRegistry::
00271 get_name(TypeHandle type, TypedObject *object) const {
00272   _lock->acquire();
00273   TypeRegistryNode *rnode = look_up(type, object);
00274   assert(rnode != (TypeRegistryNode *)NULL);
00275   string name = rnode->_name;
00276   _lock->release();
00277 
00278   return name;
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: TypeRegistry::is_derived_from
00283 //       Access: Published
00284 //  Description: Returns true if the first type is derived from the
00285 //               second type, false otherwise.
00286 //
00287 //               The "child_object" pointer is an optional pointer to
00288 //               the TypedObject class that owns the child TypeHandle.
00289 //               It is only used in case the TypeHandle is
00290 //               inadvertently undefined.
00291 //
00292 //               This function definition follows the definitions for
00293 //               look_up() and freshen_derivations() just to maximize
00294 //               the chance the the compiler will be able to inline
00295 //               the above functions.  Yeah, a compiler shouldn't
00296 //               care, but there's a big different between "shouldn't"
00297 //               and "doesn't".
00298 ////////////////////////////////////////////////////////////////////
00299 bool TypeRegistry::
00300 is_derived_from(TypeHandle child, TypeHandle base,
00301                 TypedObject *child_object) {
00302   _lock->acquire();
00303 
00304   const TypeRegistryNode *child_node = look_up(child, child_object);
00305   const TypeRegistryNode *base_node = look_up(base, (TypedObject *)NULL);
00306   assert(child_node != (TypeRegistryNode *)NULL &&
00307          base_node != (TypeRegistryNode *)NULL);
00308   freshen_derivations();
00309 
00310   bool result = TypeRegistryNode::is_derived_from(child_node, base_node);
00311   _lock->release();
00312   return result;
00313 }
00314 
00315 ////////////////////////////////////////////////////////////////////
00316 //     Function: TypeRegistry::get_num_type_handles
00317 //       Access: Published
00318 //  Description: Returns the total number of unique TypeHandles in the
00319 //               system.
00320 ////////////////////////////////////////////////////////////////////
00321 int TypeRegistry::
00322 get_num_typehandles() {
00323   _lock->acquire();
00324   int num_types = (int)_handle_registry.size();
00325   _lock->release();
00326   return num_types;
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: TypeRegistry::get_typehandle
00331 //       Access: Published
00332 //  Description: Returns the nth TypeHandle in the system.  See
00333 //               get_num_typehandles().
00334 ////////////////////////////////////////////////////////////////////
00335 TypeHandle TypeRegistry::
00336 get_typehandle(int n) {
00337   _lock->acquire();
00338   TypeRegistryNode *rnode = NULL;
00339   if (n >= 0 && n < (int)_handle_registry.size()) {
00340     rnode = _handle_registry[n];
00341   }
00342   _lock->release();
00343 
00344   if (rnode != (TypeRegistryNode *)NULL) {
00345     return rnode->_handle;
00346   }
00347 
00348   return TypeHandle::none();
00349 }
00350 
00351 ////////////////////////////////////////////////////////////////////
00352 //     Function: TypeRegistry::get_num_root_classes
00353 //       Access: Published
00354 //  Description: Returns the number of root classes--that is, classes
00355 //               that do not inherit from any other classes--known in
00356 //               the system.
00357 ////////////////////////////////////////////////////////////////////
00358 int TypeRegistry::
00359 get_num_root_classes() {
00360   _lock->acquire();
00361   freshen_derivations();
00362   int num_roots = _root_classes.size();
00363   _lock->release();
00364   return num_roots;
00365 }
00366 
00367 ////////////////////////////////////////////////////////////////////
00368 //     Function: TypeRegistry::get_root_class
00369 //       Access: Published
00370 //  Description: Returns the nth root class in the system.  See
00371 //               get_num_root_classes().
00372 ////////////////////////////////////////////////////////////////////
00373 TypeHandle TypeRegistry::
00374 get_root_class(int n) {
00375   _lock->acquire();
00376   freshen_derivations();
00377   TypeHandle handle;
00378   if (n >= 0 && n < (int)_root_classes.size()) {
00379     handle = _root_classes[n]->_handle;
00380   }
00381   _lock->release();
00382 
00383   return handle;
00384 }
00385 
00386 ////////////////////////////////////////////////////////////////////
00387 //     Function: TypeRegistry::get_num_parent_classes
00388 //       Access: Published
00389 //  Description: Returns the number of parent classes that the
00390 //               indicated type is known to have.  This may then be
00391 //               used to index into get_parent_class().  The result
00392 //               will be 0 if this class does not inherit from any
00393 //               other classes, 1 if normal, single inheritance is in
00394 //               effect, or greater than one if multiple inheritance
00395 //               is in effect.
00396 //
00397 //               The "object" pointer is an optional pointer to the
00398 //               TypedObject class that owns this TypeHandle.  It is
00399 //               only used in case the TypeHandle is inadvertantly
00400 //               undefined.
00401 ////////////////////////////////////////////////////////////////////
00402 int TypeRegistry::
00403 get_num_parent_classes(TypeHandle child, TypedObject *child_object) const {
00404   _lock->acquire();
00405   TypeRegistryNode *rnode = look_up(child, child_object);
00406   assert(rnode != (TypeRegistryNode *)NULL);
00407   int num_parents = rnode->_parent_classes.size();
00408   _lock->release();
00409   return num_parents;
00410 }
00411 
00412 ////////////////////////////////////////////////////////////////////
00413 //     Function: TypeRegistry::get_parent_class
00414 //       Access: Published
00415 //  Description: Returns the nth parent class of this type.  The index
00416 //               should be in the range 0 <= index <
00417 //               get_num_parent_classes().
00418 ////////////////////////////////////////////////////////////////////
00419 TypeHandle TypeRegistry::
00420 get_parent_class(TypeHandle child, int index) const {
00421   _lock->acquire();
00422   TypeHandle handle;
00423   TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
00424   assert(rnode != (TypeRegistryNode *)NULL);
00425   if (index >= 0 && index < (int)rnode->_parent_classes.size()) {
00426     handle = rnode->_parent_classes[index]->_handle;
00427   }
00428   _lock->release();
00429   return handle;
00430 }
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: TypeRegistry::get_num_child_classes
00434 //       Access: Published
00435 //  Description: Returns the number of child classes that the
00436 //               indicated type is known to have.  This may then be
00437 //               used to index into get_child_class().
00438 //
00439 //               The "object" pointer is an optional pointer to the
00440 //               TypedObject class that owns this TypeHandle.  It is
00441 //               only used in case the TypeHandle is inadvertantly
00442 //               undefined.
00443 ////////////////////////////////////////////////////////////////////
00444 int TypeRegistry::
00445 get_num_child_classes(TypeHandle child, TypedObject *child_object) const {
00446   _lock->acquire();
00447   TypeRegistryNode *rnode = look_up(child, child_object);
00448   assert(rnode != (TypeRegistryNode *)NULL);
00449   int num_children = rnode->_child_classes.size();
00450   _lock->release();
00451   return num_children;
00452 }
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: TypeRegistry::get_child_class
00456 //       Access: Published
00457 //  Description: Returns the nth child class of this type.  The index
00458 //               should be in the range 0 <= index <
00459 //               get_num_child_classes().
00460 ////////////////////////////////////////////////////////////////////
00461 TypeHandle TypeRegistry::
00462 get_child_class(TypeHandle child, int index) const {
00463   _lock->acquire();
00464   TypeHandle handle;
00465   TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
00466   assert(rnode != (TypeRegistryNode *)NULL);
00467   if (index >= 0 && index < (int)rnode->_child_classes.size()) {
00468     handle = rnode->_child_classes[index]->_handle;
00469   }
00470   _lock->release();
00471   return handle;
00472 }
00473 
00474 ////////////////////////////////////////////////////////////////////
00475 //     Function: TypeRegistry::get_parent_towards
00476 //       Access: Published
00477 //  Description: Returns the parent of the indicated child class that
00478 //               is in a direct line of inheritance to the indicated
00479 //               ancestor class.  This is useful in the presence of
00480 //               multiple inheritance to try to determine what
00481 //               properties an unknown type may have.
00482 //
00483 //               The "object" pointer is an optional pointer to the
00484 //               TypedObject class that owns this TypeHandle.  It is
00485 //               only used in case the TypeHandle is inadvertantly
00486 //               undefined.
00487 ////////////////////////////////////////////////////////////////////
00488 TypeHandle TypeRegistry::
00489 get_parent_towards(TypeHandle child, TypeHandle base,
00490                    TypedObject *child_object) {
00491   _lock->acquire();
00492   TypeHandle handle;
00493   const TypeRegistryNode *child_node = look_up(child, child_object);
00494   const TypeRegistryNode *base_node = look_up(base, NULL);
00495   assert(child_node != (TypeRegistryNode *)NULL && 
00496          base_node != (TypeRegistryNode *)NULL);
00497   freshen_derivations();
00498   handle = TypeRegistryNode::get_parent_towards(child_node, base_node);
00499   _lock->release();
00500   return handle;
00501 }
00502 
00503 
00504 ////////////////////////////////////////////////////////////////////
00505 //     Function: TypeRegistry::reregister_types
00506 //       Access: Published, Static
00507 //  Description: Walks through the TypeRegistry tree and makes sure
00508 //               that each type that was previously registered is
00509 //               *still* registered.  This seems to get broken in
00510 //               certain circumstances when compiled against libc5--it
00511 //               is as if the static initializer stomps on the
00512 //               _type_handle values of each class after they've been
00513 //               registered.
00514 ////////////////////////////////////////////////////////////////////
00515 void TypeRegistry::
00516 reregister_types() {
00517   init_lock();
00518   _lock->acquire();
00519   HandleRegistry::iterator ri;
00520   TypeRegistry *reg = ptr();
00521   for (ri = reg->_handle_registry.begin();
00522        ri != reg->_handle_registry.end();
00523        ++ri) {
00524     TypeRegistryNode *rnode = (*ri);
00525     if (rnode != NULL && rnode->_handle != rnode->_ref) {
00526       cerr << "Reregistering " << rnode->_name << "\n";
00527     }
00528   }
00529   _lock->release();
00530 }
00531 
00532 
00533 ////////////////////////////////////////////////////////////////////
00534 //     Function: TypeRegistry::write
00535 //       Access: Published
00536 //  Description: Makes an attempt to format the entire TypeRegistry in
00537 //               a nice way that shows the derivation tree as
00538 //               intelligently as possible.
00539 ////////////////////////////////////////////////////////////////////
00540 void TypeRegistry::
00541 write(ostream &out) const {
00542   _lock->acquire();
00543   do_write(out);
00544   _lock->release();
00545 }
00546 
00547 ////////////////////////////////////////////////////////////////////
00548 //     Function: TypeRegistry::ptr
00549 //       Access: Published, Static
00550 //  Description: Returns the pointer to the global TypeRegistry
00551 //               object.
00552 ////////////////////////////////////////////////////////////////////
00553 TypeRegistry *TypeRegistry::
00554 ptr() {
00555   init_lock();
00556   _lock->acquire();
00557   if (_global_pointer == NULL) {
00558     init_global_pointer();
00559   }
00560   _lock->release();
00561   return _global_pointer;
00562 }
00563 
00564 ////////////////////////////////////////////////////////////////////
00565 //     Function: TypeRegistry::Constructor
00566 //       Access: Private
00567 //  Description:
00568 ////////////////////////////////////////////////////////////////////
00569 TypeRegistry::
00570 TypeRegistry() {
00571   // We'll start out our handle_registry with a default entry for the
00572   // TypeHandles whose index number is zero, and are therefore
00573   // (probably) uninitialized.
00574   _handle_registry.push_back(NULL);
00575 
00576   _derivations_fresh = false;
00577 
00578   // Here's a few sanity checks on the sizes of our words.  We have to
00579   // put it here, at runtime, since there doesn't appear to be a
00580   // cross-platform compile-time way to verify that we've chosen the
00581   // right word sizes.
00582   assert(sizeof(PN_uint8) == 1 && sizeof(PN_int8) == 1);
00583   assert(sizeof(PN_uint16) == 2 && sizeof(PN_int16) == 2);
00584   assert(sizeof(PN_uint32) == 4 && sizeof(PN_int32) == 4);
00585   assert(sizeof(PN_uint64) == 8 && sizeof(PN_int64) == 8);
00586 
00587   assert(sizeof(PN_float32) == 4);
00588   assert(sizeof(PN_float64) == 8);
00589 }
00590 
00591 ////////////////////////////////////////////////////////////////////
00592 //     Function: TypeRegistry::init_global_pointer
00593 //       Access: Private, Static
00594 //  Description: Constructs the TypeRegistry object for the first
00595 //               time.
00596 ////////////////////////////////////////////////////////////////////
00597 void TypeRegistry::
00598 init_global_pointer() {
00599   init_memory_hook();
00600   _global_pointer = new TypeRegistry;
00601 }
00602 
00603 ////////////////////////////////////////////////////////////////////
00604 //     Function: TypeRegistry::rebuild_derivations
00605 //       Access: Private
00606 //  Description: Rebuilds the derivation data structures after some
00607 //               derivation relationship has been modified, so that
00608 //               class relationships can quickly be determined.
00609 ////////////////////////////////////////////////////////////////////
00610 void TypeRegistry::
00611 rebuild_derivations() {
00612   // First, remove all of the old data from the last type
00613   // rebuild_derivations() was called.
00614   _root_classes.clear();
00615 
00616   HandleRegistry::iterator hi;
00617   for (hi = _handle_registry.begin();
00618        hi != _handle_registry.end();
00619        ++hi) {
00620     TypeRegistryNode *node = *hi;
00621     if (node != (TypeRegistryNode *)NULL) {
00622       node->clear_subtree();
00623     }
00624   }
00625   
00626   // Start by getting the list of root classes: those classes which do
00627   // not derive from anything.
00628   for (hi = _handle_registry.begin();
00629        hi != _handle_registry.end();
00630        ++hi) {
00631     TypeRegistryNode *node = *hi;
00632     if (node != NULL && node->_parent_classes.empty()) {
00633       _root_classes.push_back(node);
00634 
00635       // Also, for each root class, define a subtree.
00636       node->define_subtree();
00637     }
00638   }
00639 }
00640 
00641 ////////////////////////////////////////////////////////////////////
00642 //     Function: TypeRegistry::do_write
00643 //       Access: Private
00644 //  Description: The private implementation of write(), this assumes
00645 //               the lock is already held.
00646 ////////////////////////////////////////////////////////////////////
00647 void TypeRegistry::
00648 do_write(ostream &out) const {
00649   // Recursively write out the tree, starting from each node that has
00650   // no parent.
00651   HandleRegistry::const_iterator hi;
00652   for (hi = _handle_registry.begin();
00653        hi != _handle_registry.end();
00654        ++hi) {
00655     const TypeRegistryNode *root = *hi;
00656     if (root != NULL && root->_parent_classes.empty()) {
00657       write_node(out, 2, root);
00658     }
00659   }
00660 }
00661 
00662 ////////////////////////////////////////////////////////////////////
00663 //     Function: TypeRegistry::write_node
00664 //       Access: Private
00665 //  Description: Writes a single TypeRegistryNode out, along with all of
00666 //               its descendants.  Assumes the lock is already held.
00667 ////////////////////////////////////////////////////////////////////
00668 void TypeRegistry::
00669 write_node(ostream &out, int indent_level, const TypeRegistryNode *node) const {
00670   indent(out, indent_level) << node->_handle.get_index() << " " << node->_name;
00671   if (!node->_parent_classes.empty()) {
00672     out << " : " << node->_parent_classes[0]->_name;
00673     for (int pi = 1; pi < (int)node->_parent_classes.size(); pi++) {
00674       out << ", " << node->_parent_classes[pi]->_name;
00675     }
00676   }
00677   out << "\n";
00678 
00679   for (int i = 0; i < (int)node->_child_classes.size(); i++) {
00680     write_node(out, indent_level + 2, node->_child_classes[i]);
00681   }
00682 }
00683 
00684 ////////////////////////////////////////////////////////////////////
00685 //     Function: TypeRegistry::look_up
00686 //       Access: Private
00687 //  Description: Returns the TypeRegistryNode associated with the
00688 //               indicated TypeHandle.  If there is no associated
00689 //               TypeRegistryNode, reports an error condition and
00690 //               returns NULL.
00691 //
00692 //               The associated TypedObject pointer is the pointer to
00693 //               the object that owns the handle, if available.  It is
00694 //               only used in an error condition, if for some reason
00695 //               the handle was uninitialized.
00696 //
00697 //               Assumes the lock is already held.
00698 ////////////////////////////////////////////////////////////////////
00699 TypeRegistryNode *TypeRegistry::
00700 look_up(TypeHandle handle, TypedObject *object) const {
00701 #ifndef NDEBUG
00702   if (handle._index == 0) {
00703     // The TypeHandle is unregistered.  This is an error condition.
00704 
00705     if (object != NULL) {
00706       // But we're lucky enough to have a TypedObject pointer handy!
00707       // Maybe we can use it to resolve the error.  We have to drop
00708       // the lock while we do this, so we don't get a recursive lock.
00709       _lock->release();
00710       handle = object->force_init_type();
00711       _lock->acquire();
00712       if (handle._index == 0) {
00713         // Strange.
00714         cerr
00715           << "Unable to force_init_type() on unregistered TypeHandle.\n";
00716         return NULL;
00717       }
00718       if (handle == object->get_type()) {
00719         // Problem solved!
00720         cerr
00721           << "Type " << handle << " was unregistered!\n";
00722       } else {
00723         // No good; it looks like the TypeHandle belongs to a class
00724         // that defined get_type(), but didn't define
00725         // force_init_type().
00726         cerr
00727           << "Attempt to reference unregistered TypeHandle.  Type is of some\n"
00728           << "class derived from " << handle << " that doesn't define a good\n"
00729           << "force_init_type() method.\n";
00730         return NULL;
00731       }
00732 
00733     } else {
00734       // We don't have a TypedObject pointer, so there's nothing we
00735       // can do about it.
00736       cerr
00737         << "Attempt to reference unregistered TypeHandle!\n"
00738         << "Registered TypeHandles are:\n";
00739       write(cerr);
00740       return NULL;
00741     }
00742   }
00743 
00744   if (handle._index < 0 ||
00745       handle._index >= (int)_handle_registry.size()) {
00746     cerr
00747       << "Invalid TypeHandle index " << handle._index
00748       << "!  Is memory corrupt?\n";
00749     return NULL;
00750   }
00751 #endif  // NDEBUG
00752 
00753   return _handle_registry[handle._index];
00754 }
00755 
00756 ////////////////////////////////////////////////////////////////////
00757 //     Function: get_best_parent_from_Set
00758 //       Access: Private
00759 ///////////////////////////////////////////////////////////////////
00760 extern "C" int 
00761 get_best_parent_from_Set(int id, const std::set<int> &this_set) {
00762   // most common case..
00763   if (this_set.find(id) != this_set.end()) {
00764     return id;
00765   }
00766 
00767   TypeHandle th = TypeRegistry::ptr()->find_type_by_id(id);
00768   if (th == TypeHandle::none()) {
00769     return -1;
00770   }
00771 
00772   return th.get_best_parent_from_Set(this_set);
00773 }
00774 
 All Classes Functions Variables Enumerations