Panda3D
attribNodeRegistry.cxx
1 // Filename: attribNodeRegistry.cxx
2 // Created by: drose (07Jul07)
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 "attribNodeRegistry.h"
16 #include "lightMutexHolder.h"
17 
18 AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr;
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: AttribNodeRegistry::Constructor
22 // Access: Protected
23 // Description:
24 ////////////////////////////////////////////////////////////////////
25 AttribNodeRegistry::
26 AttribNodeRegistry() {
27 }
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: AttribNodeRegistry::add_node
31 // Access: Published
32 // Description: Adds the indicated NodePath to the registry. The
33 // name and type of the node are noted at the time of
34 // this call; if the name changes later, it will not
35 // update the registry index.
36 //
37 // The NodePath must reference some kind of an attribute
38 // node, such as a LightNode or a PlaneNode. When bam
39 // files that reference an attribute node of the same
40 // type and the same name are loaded, they will quietly
41 // be redirected to reference this NodePath.
42 //
43 // If there is already a node matching the indicated
44 // name and type, it will be replaced.
45 ////////////////////////////////////////////////////////////////////
47 add_node(const NodePath &attrib_node) {
48  nassertv(!attrib_node.is_empty());
49  LightMutexHolder holder(_lock);
50 
51  pair<Entries::iterator, bool> result = _entries.insert(Entry(attrib_node));
52  if (!result.second) {
53  // Replace an existing node.
54  (*result.first)._node = attrib_node;
55  }
56 }
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: AttribNodeRegistry::remove_node
60 // Access: Published
61 // Description: Removes the indicated NodePath from the registry.
62 // The name of the node must not have changed since the
63 // matching call to add_node(), or it will not be
64 // successfully removed.
65 //
66 // Returns true if the NodePath is found and removed,
67 // false if it is not found (for instance, because the
68 // name has changed).
69 ////////////////////////////////////////////////////////////////////
71 remove_node(const NodePath &attrib_node) {
72  nassertr(!attrib_node.is_empty(), false);
73  LightMutexHolder holder(_lock);
74  Entries::iterator ei = _entries.find(Entry(attrib_node));
75  if (ei != _entries.end()) {
76  _entries.erase(ei);
77  return true;
78  }
79  return false;
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: AttribNodeRegistry::lookup_node
84 // Access: Published
85 // Description: Looks up the indicated NodePath in the registry. If
86 // there is a node already in the registry with the
87 // matching name and type, returns that NodePath
88 // instead; otherwise, returns the original NodePath.
89 ////////////////////////////////////////////////////////////////////
91 lookup_node(const NodePath &orig_node) const {
92  nassertr(!orig_node.is_empty(), orig_node);
93 
94  LightMutexHolder holder(_lock);
95  Entries::const_iterator ei = _entries.find(Entry(orig_node));
96  if (ei != _entries.end()) {
97  return (*ei)._node;
98  }
99  return orig_node;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: AttribNodeRegistry::get_num_nodes
104 // Access: Published
105 // Description: Returns the total number of nodes in the registry.
106 ////////////////////////////////////////////////////////////////////
108 get_num_nodes() const {
109  LightMutexHolder holder(_lock);
110  return _entries.size();
111 }
112 
113 ////////////////////////////////////////////////////////////////////
114 // Function: AttribNodeRegistry::get_node
115 // Access: Published
116 // Description: Returns the nth NodePath recorded in the registry.
117 ////////////////////////////////////////////////////////////////////
119 get_node(int n) const {
120  LightMutexHolder holder(_lock);
121  nassertr(n >= 0 && n < (int)_entries.size(), NodePath());
122  return _entries[n]._node;
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: AttribNodeRegistry::get_node_type
127 // Access: Published
128 // Description: Returns the type of the nth node, as recorded in the
129 // registry.
130 ////////////////////////////////////////////////////////////////////
132 get_node_type(int n) const {
133  LightMutexHolder holder(_lock);
134  nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none());
135  return _entries[n]._type;
136 }
137 
138 ////////////////////////////////////////////////////////////////////
139 // Function: AttribNodeRegistry::get_node_name
140 // Access: Published
141 // Description: Returns the name of the nth node, as recorded in the
142 // registry. This will be the node name as it was at
143 // the time the node was recorded; if the node has
144 // changed names since then, this will still return the
145 // original name.
146 ////////////////////////////////////////////////////////////////////
148 get_node_name(int n) const {
149  LightMutexHolder holder(_lock);
150  nassertr(n >= 0 && n < (int)_entries.size(), string());
151  return _entries[n]._name;
152 }
153 
154 ////////////////////////////////////////////////////////////////////
155 // Function: AttribNodeRegistry::find_node
156 // Access: Published
157 // Description: Returns the index number of the indicated NodePath in
158 // the registry (assuming its name hasn't changed since
159 // it was recorded in the registry), or -1 if the
160 // NodePath cannot be found (for instance, because its
161 // name has changed).
162 ////////////////////////////////////////////////////////////////////
164 find_node(const NodePath &attrib_node) const {
165  nassertr(!attrib_node.is_empty(), -1);
166  LightMutexHolder holder(_lock);
167  Entries::const_iterator ei = _entries.find(Entry(attrib_node));
168  if (ei != _entries.end()) {
169  return ei - _entries.begin();
170  }
171  return -1;
172 }
173 
174 ////////////////////////////////////////////////////////////////////
175 // Function: AttribNodeRegistry::find_node
176 // Access: Published
177 // Description: Returns the index number of the node with the
178 // indicated type and name in the registry, or -1 if
179 // there is no such node in the registry.
180 ////////////////////////////////////////////////////////////////////
182 find_node(TypeHandle type, const string &name) const {
183  LightMutexHolder holder(_lock);
184  Entries::const_iterator ei = _entries.find(Entry(type, name));
185  if (ei != _entries.end()) {
186  return ei - _entries.begin();
187  }
188  return -1;
189 }
190 
191 ////////////////////////////////////////////////////////////////////
192 // Function: AttribNodeRegistry::remove_node
193 // Access: Published
194 // Description: Removes the nth node from the registry.
195 ////////////////////////////////////////////////////////////////////
197 remove_node(int n) {
198  LightMutexHolder holder(_lock);
199  nassertv(n >= 0 && n < (int)_entries.size());
200  _entries.erase(_entries.begin() + n);
201 }
202 
203 ////////////////////////////////////////////////////////////////////
204 // Function: AttribNodeRegistry::clear
205 // Access: Published
206 // Description: Removes all nodes from the registry.
207 ////////////////////////////////////////////////////////////////////
209 clear() {
210  LightMutexHolder holder(_lock);
211  _entries.clear();
212 }
213 
214 ////////////////////////////////////////////////////////////////////
215 // Function: AttribNodeRegistry::output
216 // Access: Published
217 // Description:
218 ////////////////////////////////////////////////////////////////////
219 void AttribNodeRegistry::
220 output(ostream &out) const {
221  LightMutexHolder holder(_lock);
222 
223  typedef pmap<TypeHandle, int> Counts;
224  Counts counts;
225 
226  Entries::const_iterator ei;
227  for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
228  TypeHandle type = (*ei)._type;
229  Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first;
230  ++((*ci).second);
231  }
232 
233  out << _entries.size() << " entries";
234 
235  if (!counts.empty()) {
236  Counts::iterator ci = counts.begin();
237  out << " (" << (*ci).first << ":" << (*ci).second;
238  ++ci;
239  while (ci != counts.end()) {
240  out << ", " << (*ci).first << ":" << (*ci).second;
241  ++ci;
242  }
243  out << ")";
244  }
245 }
246 
247 ////////////////////////////////////////////////////////////////////
248 // Function: AttribNodeRegistry::write
249 // Access: Published
250 // Description:
251 ////////////////////////////////////////////////////////////////////
252 void AttribNodeRegistry::
253 write(ostream &out) const {
254  LightMutexHolder holder(_lock);
255 
256  Entries::const_iterator ei;
257  for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
258  const Entry &entry = (*ei);
259  out << entry._type << ", \"" << entry._name << "\": " << entry._node
260  << "\n";
261  }
262 }
263 
264 ////////////////////////////////////////////////////////////////////
265 // Function: AttribNodeRegistry::make_global_ptr
266 // Access: Private, Static
267 // Description:
268 ////////////////////////////////////////////////////////////////////
269 void AttribNodeRegistry::
270 make_global_ptr() {
273  ((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
274  if (result != NULL) {
275  // Someone else got there first.
276  delete ptr;
277  }
278  assert(_global_ptr != (AttribNodeRegistry *)NULL);
279 }
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
int get_num_nodes() const
Returns the total number of nodes in the registry.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
size_type_0 size() const
Returns the number of elements in the ordered vector.
void clear()
Removes all elements from the ordered vector.
This global object records NodePaths that are referenced by scene graph attribs, such as ClipPlaneAtt...
bool remove_node(const NodePath &attrib_node)
Removes the indicated NodePath from the registry.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
string get_node_name(int n) const
Returns the name of the nth node, as recorded in the registry.
int find_node(const NodePath &attrib_node) const
Returns the index number of the indicated NodePath in the registry (assuming its name hasn&#39;t changed ...
Similar to MutexHolder, but for a light mutex.
void add_node(const NodePath &attrib_node)
Adds the indicated NodePath to the registry.
NodePath get_node(int n) const
Returns the nth NodePath recorded in the registry.
NodePath lookup_node(const NodePath &orig_node) const
Looks up the indicated NodePath in the registry.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
void clear()
Removes all nodes from the registry.
TypeHandle get_node_type(int n) const
Returns the type of the nth node, as recorded in the registry.
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.