Panda3D

attribNodeRegistry.cxx

00001 // Filename: attribNodeRegistry.cxx
00002 // Created by:  drose (07Jul07)
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 "attribNodeRegistry.h"
00016 #include "lightMutexHolder.h"
00017 
00018 AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr;
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: AttribNodeRegistry::Constructor
00022 //       Access: Protected
00023 //  Description: 
00024 ////////////////////////////////////////////////////////////////////
00025 AttribNodeRegistry::
00026 AttribNodeRegistry() {
00027 }
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: AttribNodeRegistry::add_node
00031 //       Access: Published
00032 //  Description: Adds the indicated NodePath to the registry.  The
00033 //               name and type of the node are noted at the time of
00034 //               this call; if the name changes later, it will not
00035 //               update the registry index.
00036 //
00037 //               The NodePath must reference some kind of an attribute
00038 //               node, such as a LightNode or a PlaneNode.  When bam
00039 //               files that reference an attribute node of the same
00040 //               type and the same name are loaded, they will quietly
00041 //               be redirected to reference this NodePath.
00042 //
00043 //               If there is already a node matching the indicated
00044 //               name and type, it will be replaced.
00045 ////////////////////////////////////////////////////////////////////
00046 void AttribNodeRegistry::
00047 add_node(const NodePath &attrib_node) {
00048   nassertv(!attrib_node.is_empty());
00049   LightMutexHolder holder(_lock);
00050 
00051   pair<Entries::iterator, bool> result = _entries.insert(Entry(attrib_node));
00052   if (!result.second) {
00053     // Replace an existing node.
00054     (*result.first)._node = attrib_node;
00055   }
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: AttribNodeRegistry::remove_node
00060 //       Access: Published
00061 //  Description: Removes the indicated NodePath from the registry.
00062 //               The name of the node must not have changed since the
00063 //               matching call to add_node(), or it will not be
00064 //               successfully removed.
00065 //
00066 //               Returns true if the NodePath is found and removed,
00067 //               false if it is not found (for instance, because the
00068 //               name has changed).
00069 ////////////////////////////////////////////////////////////////////
00070 bool AttribNodeRegistry::
00071 remove_node(const NodePath &attrib_node) {
00072   nassertr(!attrib_node.is_empty(), false);
00073   LightMutexHolder holder(_lock);
00074   Entries::iterator ei = _entries.find(Entry(attrib_node));
00075   if (ei != _entries.end()) {
00076     _entries.erase(ei);
00077     return true;
00078   }
00079   return false;
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: AttribNodeRegistry::lookup_node
00084 //       Access: Published
00085 //  Description: Looks up the indicated NodePath in the registry.  If
00086 //               there is a node already in the registry with the
00087 //               matching name and type, returns that NodePath
00088 //               instead; otherwise, returns the original NodePath.
00089 ////////////////////////////////////////////////////////////////////
00090 NodePath AttribNodeRegistry::
00091 lookup_node(const NodePath &orig_node) const {
00092   nassertr(!orig_node.is_empty(), orig_node);
00093 
00094   LightMutexHolder holder(_lock);
00095   Entries::const_iterator ei = _entries.find(Entry(orig_node));
00096   if (ei != _entries.end()) {
00097     return (*ei)._node;
00098   }
00099   return orig_node;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: AttribNodeRegistry::get_num_nodes
00104 //       Access: Published
00105 //  Description: Returns the total number of nodes in the registry.
00106 ////////////////////////////////////////////////////////////////////
00107 int AttribNodeRegistry::
00108 get_num_nodes() const {
00109   LightMutexHolder holder(_lock);
00110   return _entries.size();
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: AttribNodeRegistry::get_node
00115 //       Access: Published
00116 //  Description: Returns the nth NodePath recorded in the registry.
00117 ////////////////////////////////////////////////////////////////////
00118 NodePath AttribNodeRegistry::
00119 get_node(int n) const {
00120   LightMutexHolder holder(_lock);
00121   nassertr(n >= 0 && n < (int)_entries.size(), NodePath());
00122   return _entries[n]._node;
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: AttribNodeRegistry::get_node_type
00127 //       Access: Published
00128 //  Description: Returns the type of the nth node, as recorded in the
00129 //               registry.
00130 ////////////////////////////////////////////////////////////////////
00131 TypeHandle AttribNodeRegistry::
00132 get_node_type(int n) const {
00133   LightMutexHolder holder(_lock);
00134   nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none());
00135   return _entries[n]._type;
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: AttribNodeRegistry::get_node_name
00140 //       Access: Published
00141 //  Description: Returns the name of the nth node, as recorded in the
00142 //               registry.  This will be the node name as it was at
00143 //               the time the node was recorded; if the node has
00144 //               changed names since then, this will still return the
00145 //               original name.
00146 ////////////////////////////////////////////////////////////////////
00147 string AttribNodeRegistry::
00148 get_node_name(int n) const {
00149   LightMutexHolder holder(_lock);
00150   nassertr(n >= 0 && n < (int)_entries.size(), string());
00151   return _entries[n]._name;
00152 }
00153 
00154 ////////////////////////////////////////////////////////////////////
00155 //     Function: AttribNodeRegistry::find_node
00156 //       Access: Published
00157 //  Description: Returns the index number of the indicated NodePath in
00158 //               the registry (assuming its name hasn't changed since
00159 //               it was recorded in the registry), or -1 if the
00160 //               NodePath cannot be found (for instance, because its
00161 //               name has changed).
00162 ////////////////////////////////////////////////////////////////////
00163 int AttribNodeRegistry::
00164 find_node(const NodePath &attrib_node) const {
00165   nassertr(!attrib_node.is_empty(), -1);
00166   LightMutexHolder holder(_lock);
00167   Entries::const_iterator ei = _entries.find(Entry(attrib_node));
00168   if (ei != _entries.end()) {
00169     return ei - _entries.begin();
00170   }
00171   return -1;
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: AttribNodeRegistry::find_node
00176 //       Access: Published
00177 //  Description: Returns the index number of the node with the
00178 //               indicated type and name in the registry, or -1 if
00179 //               there is no such node in the registry.
00180 ////////////////////////////////////////////////////////////////////
00181 int AttribNodeRegistry::
00182 find_node(TypeHandle type, const string &name) const {
00183   LightMutexHolder holder(_lock);
00184   Entries::const_iterator ei = _entries.find(Entry(type, name));
00185   if (ei != _entries.end()) {
00186     return ei - _entries.begin();
00187   }
00188   return -1;
00189 }
00190 
00191 ////////////////////////////////////////////////////////////////////
00192 //     Function: AttribNodeRegistry::remove_node
00193 //       Access: Published
00194 //  Description: Removes the nth node from the registry.
00195 ////////////////////////////////////////////////////////////////////
00196 void AttribNodeRegistry::
00197 remove_node(int n) {
00198   LightMutexHolder holder(_lock);
00199   nassertv(n >= 0 && n < (int)_entries.size());
00200   _entries.erase(_entries.begin() + n);
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: AttribNodeRegistry::clear
00205 //       Access: Published
00206 //  Description: Removes all nodes from the registry.
00207 ////////////////////////////////////////////////////////////////////
00208 void AttribNodeRegistry::
00209 clear() {
00210   LightMutexHolder holder(_lock);
00211   _entries.clear();
00212 }
00213 
00214 ////////////////////////////////////////////////////////////////////
00215 //     Function: AttribNodeRegistry::output
00216 //       Access: Published
00217 //  Description: 
00218 ////////////////////////////////////////////////////////////////////
00219 void AttribNodeRegistry::
00220 output(ostream &out) const {
00221   LightMutexHolder holder(_lock);
00222 
00223   typedef pmap<TypeHandle, int> Counts;
00224   Counts counts;
00225 
00226   Entries::const_iterator ei;
00227   for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
00228     TypeHandle type = (*ei)._type;
00229     Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first;
00230     ++((*ci).second);
00231   }
00232 
00233   out << _entries.size() << " entries";
00234 
00235   if (!counts.empty()) {
00236     Counts::iterator ci = counts.begin();
00237     out << " (" << (*ci).first << ":" << (*ci).second;
00238     ++ci;
00239     while (ci != counts.end()) {
00240       out << ", " << (*ci).first << ":" << (*ci).second;
00241       ++ci;
00242     }
00243     out << ")";
00244   }
00245 }
00246 
00247 ////////////////////////////////////////////////////////////////////
00248 //     Function: AttribNodeRegistry::write
00249 //       Access: Published
00250 //  Description: 
00251 ////////////////////////////////////////////////////////////////////
00252 void AttribNodeRegistry::
00253 write(ostream &out) const {
00254   LightMutexHolder holder(_lock);
00255 
00256   Entries::const_iterator ei;
00257   for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
00258     const Entry &entry = (*ei);
00259     out << entry._type << ", \"" << entry._name << "\": " << entry._node
00260         << "\n";
00261   }
00262 }
00263 
00264 ////////////////////////////////////////////////////////////////////
00265 //     Function: AttribNodeRegistry::make_global_ptr
00266 //       Access: Private, Static
00267 //  Description: 
00268 ////////////////////////////////////////////////////////////////////
00269 void AttribNodeRegistry::
00270 make_global_ptr() {
00271   AttribNodeRegistry *ptr = new AttribNodeRegistry;
00272   void *result = AtomicAdjust::compare_and_exchange_ptr
00273     ((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
00274   if (result != NULL) {
00275     // Someone else got there first.
00276     delete ptr;
00277   }
00278   assert(_global_ptr != (AttribNodeRegistry *)NULL);
00279 }
 All Classes Functions Variables Enumerations