Panda3D
|
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