Panda3D
renderAttrib.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file renderAttrib.cxx
10  * @author drose
11  * @date 2002-02-21
12  */
13 
14 #include "renderAttrib.h"
15 #include "bamReader.h"
16 #include "indent.h"
17 #include "config_pgraph.h"
18 #include "lightReMutexHolder.h"
19 #include "pStatTimer.h"
20 
21 using std::ostream;
22 
23 LightReMutex *RenderAttrib::_attribs_lock = nullptr;
24 RenderAttrib::Attribs *RenderAttrib::_attribs = nullptr;
25 TypeHandle RenderAttrib::_type_handle;
26 
27 size_t RenderAttrib::_garbage_index = 0;
28 
29 PStatCollector RenderAttrib::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
30 
31 /**
32  *
33  */
34 RenderAttrib::
35 RenderAttrib() {
36  if (_attribs == nullptr) {
37  init_attribs();
38  }
39  _saved_entry = -1;
40 }
41 
42 /**
43  * The destructor is responsible for removing the RenderAttrib from the global
44  * set if it is there.
45  */
47 ~RenderAttrib() {
48  LightReMutexHolder holder(*_attribs_lock);
49 
50  // unref() should have cleared this.
51  nassertv(_saved_entry == -1);
52 }
53 
54 /**
55  * Intended to be overridden by derived RenderAttrib types to specify how two
56  * consecutive RenderAttrib objects of the same type interact.
57  *
58  * This should return false if a RenderAttrib on a higher node will compose
59  * into a RenderAttrib on a lower node that has a higher override value, or
60  * true if the lower RenderAttrib will completely replace the state.
61  *
62  * The default behavior is false: normally, a RenderAttrib in the graph cannot
63  * completely override a RenderAttrib above it, regardless of its override
64  * value--instead, the two attribs are composed. But for some kinds of
65  * RenderAttribs, it is useful to allow this kind of override.
66  *
67  * This method only handles the one special case of a lower RenderAttrib with
68  * a higher override value. If the higher RenderAttrib has a higher override
69  * value, it always completely overrides. And if both RenderAttribs have the
70  * same override value, they are always composed.
71  */
74  return false;
75 }
76 
77 /**
78  * Should be overridden by derived classes to return true if cull_callback()
79  * has been defined. Otherwise, returns false to indicate cull_callback()
80  * does not need to be called for this node during the cull traversal.
81  */
83 has_cull_callback() const {
84  return false;
85 }
86 
87 /**
88  * If has_cull_callback() returns true, this function will be called during
89  * the cull traversal to perform any additional operations that should be
90  * performed at cull time.
91  *
92  * This is called each time the RenderAttrib is discovered applied to a Geom
93  * in the traversal. It should return true if the Geom is visible, false if
94  * it should be omitted.
95  */
98  return true;
99 }
100 
101 /**
102  * This method overrides ReferenceCount::unref() to clear the pointer from the
103  * global object pool when its reference count goes to zero.
104  */
106 unref() const {
107  if (!state_cache || garbage_collect_states) {
108  // If we're not using the cache at all, or if we're relying on garbage
109  // collection, just allow the pointer to unref normally.
110  return ReferenceCount::unref();
111  }
112 
113  // Here is the normal refcounting case, with a normal cache, and without
114  // garbage collection in effect. In this case we will pull the object out
115  // of the cache when its reference count goes to 0.
116 
117  // We always have to grab the lock, since we will definitely need to be
118  // holding it if we happen to drop the reference count to 0. Having to grab
119  // the lock at every call to unref() is a big limiting factor on
120  // parallelization.
121  LightReMutexHolder holder(*_attribs_lock);
122 
123  if (ReferenceCount::unref()) {
124  // The reference count is still nonzero.
125  return true;
126  }
127 
128  // The reference count has just reached zero. Make sure the object is
129  // removed from the global object pool, before anyone else finds it and
130  // tries to ref it.
131  ((RenderAttrib *)this)->release_new();
132 
133  return false;
134 }
135 
136 /**
137  *
138  */
139 void RenderAttrib::
140 output(ostream &out) const {
141  out << get_type();
142 }
143 
144 /**
145  *
146  */
147 void RenderAttrib::
148 write(ostream &out, int indent_level) const {
149  indent(out, indent_level) << *this << "\n";
150 }
151 
152 /**
153  * Returns the total number of unique RenderAttrib objects allocated in the
154  * world. This will go up and down during normal operations.
155  */
157 get_num_attribs() {
158  LightReMutexHolder holder(*_attribs_lock);
159 
160  if (_attribs == nullptr) {
161  return 0;
162  }
163  return _attribs->get_num_entries();
164 }
165 
166 /**
167  * Lists all of the RenderAttribs in the cache to the output stream, one per
168  * line. This can be quite a lot of output if the cache is large, so be
169  * prepared.
170  */
172 list_attribs(ostream &out) {
173  LightReMutexHolder holder(*_attribs_lock);
174 
175  size_t size = _attribs->get_num_entries();
176  out << size << " attribs:\n";
177  for (size_t si = 0; si < size; ++si) {
178  const RenderAttrib *attrib = _attribs->get_key(si);
179  attrib->write(out, 2);
180  }
181 }
182 
183 /**
184  * Performs a garbage-collection cycle. This is called automatically from
185  * RenderState::garbage_collect(); see that method for more information.
186  */
188 garbage_collect() {
189  if (_attribs == nullptr || !garbage_collect_states) {
190  return 0;
191  }
192  LightReMutexHolder holder(*_attribs_lock);
193 
194  PStatTimer timer(_garbage_collect_pcollector);
195  size_t orig_size = _attribs->get_num_entries();
196 
197 #ifdef _DEBUG
198  nassertr(_attribs->validate(), 0);
199 #endif
200 
201  // How many elements to process this pass?
202  size_t size = orig_size;
203  size_t num_this_pass = std::max(0, int(size * garbage_collect_states_rate));
204  if (num_this_pass <= 0) {
205  return 0;
206  }
207 
208  size_t si = _garbage_index;
209  if (si >= size) {
210  si = 0;
211  }
212 
213  num_this_pass = std::min(num_this_pass, size);
214  size_t stop_at_element = (si + num_this_pass) % size;
215 
216  do {
217  RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
218  if (!attrib->unref_if_one()) {
219  // This attrib has recently been unreffed to 1 (the one we added when
220  // we stored it in the cache). Now it's time to delete it. This is
221  // safe, because we're holding the _attribs_lock, so it's not possible
222  // for some other thread to find the attrib in the cache and ref it
223  // while we're doing this. Also, we've just made sure to unref it to 0,
224  // to ensure that another thread can't get it via a weak pointer.
225  attrib->release_new();
226  delete attrib;
227 
228  // When we removed it from the hash map, it swapped the last element
229  // with the one we just removed. So the current index contains one we
230  // still need to visit.
231  --size;
232  --si;
233  if (stop_at_element > 0) {
234  --stop_at_element;
235  }
236  }
237 
238  si = (si + 1) % size;
239  } while (si != stop_at_element);
240  _garbage_index = si;
241 
242  nassertr(_attribs->get_num_entries() == size, 0);
243 
244 #ifdef _DEBUG
245  nassertr(_attribs->validate(), 0);
246 #endif
247 
248  // If we just cleaned up a lot of attribs, see if we can reduce the table in
249  // size. This will help reduce iteration overhead in the future.
250  _attribs->consider_shrink_table();
251 
252  return (int)orig_size - (int)size;
253 }
254 
255 /**
256  * Ensures that the cache is still stored in sorted order. Returns true if
257  * so, false if there is a problem (which implies someone has modified one of
258  * the supposedly-const RenderAttrib objects).
259  */
262  LightReMutexHolder holder(*_attribs_lock);
263  if (_attribs->is_empty()) {
264  return true;
265  }
266 
267  if (!_attribs->validate()) {
268  pgraph_cat.error()
269  << "RenderAttrib::_attribs cache is invalid!\n";
270 
271  size_t size = _attribs->get_num_entries();
272  for (size_t si = 0; si < size; ++si) {
273  const RenderAttrib *attrib = _attribs->get_key(si);
274  //cerr << si << ": " << attrib << "\n";
275  attrib->write(std::cerr, 2);
276  }
277 
278  return false;
279  }
280 
281  size_t size = _attribs->get_num_entries();
282  size_t si = 0;
283  nassertr(si < size, false);
284  nassertr(_attribs->get_key(si)->get_ref_count() >= 0, false);
285  size_t snext = si;
286  ++snext;
287  while (snext < size) {
288  nassertr(_attribs->get_key(snext)->get_ref_count() >= 0, false);
289  const RenderAttrib *ssi = _attribs->get_key(si);
290  const RenderAttrib *ssnext = _attribs->get_key(snext);
291  int c = ssi->compare_to(*ssnext);
292  int ci = ssnext->compare_to(*ssi);
293  if ((ci < 0) != (c > 0) ||
294  (ci > 0) != (c < 0) ||
295  (ci == 0) != (c == 0)) {
296  pgraph_cat.error()
297  << "RenderAttrib::compare_to() not defined properly!\n";
298  pgraph_cat.error(false)
299  << "(a, b): " << c << "\n";
300  pgraph_cat.error(false)
301  << "(b, a): " << ci << "\n";
302  ssi->write(pgraph_cat.error(false), 2);
303  ssnext->write(pgraph_cat.error(false), 2);
304  return false;
305  }
306  si = snext;
307  ++snext;
308  }
309 
310  return true;
311 }
312 
313 /**
314  * This function is used by derived RenderAttrib types to share a common
315  * RenderAttrib pointer for all equivalent RenderAttrib objects.
316  *
317  * This is different from return_unique() in that it does not actually
318  * guarantee a unique pointer, unless uniquify-attribs is set.
319  */
320 CPT(RenderAttrib) RenderAttrib::
321 return_new(RenderAttrib *attrib) {
322  nassertr(attrib != nullptr, attrib);
323  if (!uniquify_attribs) {
324  attrib->calc_hash();
325  return attrib;
326  }
327 
328  return return_unique(attrib);
329 }
330 
331 /**
332  * This function is used by derived RenderAttrib types to share a common
333  * RenderAttrib pointer for all equivalent RenderAttrib objects.
334  *
335  * The make() function of the derived type should create a new RenderAttrib
336  * and pass it through return_new(), which will either save the pointer and
337  * return it unchanged (if this is the first similar such object) or delete it
338  * and return an equivalent pointer (if there was already a similar object
339  * saved).
340  */
341 CPT(RenderAttrib) RenderAttrib::
342 return_unique(RenderAttrib *attrib) {
343  nassertr(attrib != nullptr, attrib);
344 
345  attrib->calc_hash();
346 
347  if (!state_cache) {
348  return attrib;
349  }
350 
351 #ifndef NDEBUG
352  if (paranoid_const) {
353  nassertr(validate_attribs(), attrib);
354  }
355 #endif
356 
357  LightReMutexHolder holder(*_attribs_lock);
358 
359  if (attrib->_saved_entry != -1) {
360  // This attrib is already in the cache. nassertr(_attribs->find(attrib)
361  // == attrib->_saved_entry, attrib);
362  return attrib;
363  }
364 
365  int si = _attribs->find(attrib);
366  if (si != -1) {
367  // There's an equivalent attrib already in the set. Return it. If this
368  // is a newly created RenderAttrib, though, be sure to delete it.
369  if (attrib->get_ref_count() == 0) {
370  delete attrib;
371  }
372  return _attribs->get_key(si);
373  }
374 
375  // Not already in the set; add it.
376  if (garbage_collect_states) {
377  // If we'll be garbage collecting attribs explicitly, we'll increment the
378  // reference count when we store it in the cache, so that it won't be
379  // deleted while it's in it.
380  attrib->ref();
381  }
382  si = _attribs->store(attrib, nullptr);
383 
384  // Save the index and return the input attrib.
385  attrib->_saved_entry = si;
386  return attrib;
387 }
388 
389 /**
390  * Intended to be overridden by derived RenderAttrib types to return a unique
391  * number indicating whether this RenderAttrib is equivalent to the other one.
392  *
393  * This should return 0 if the two RenderAttrib objects are equivalent, a
394  * number less than zero if this one should be sorted before the other one,
395  * and a number greater than zero otherwise.
396  *
397  * This will only be called with two RenderAttrib objects whose get_type()
398  * functions return the same.
399  */
400 int RenderAttrib::
401 compare_to_impl(const RenderAttrib *other) const {
402  return 0;
403 }
404 
405 /**
406  * Intended to be overridden by derived RenderAttrib types to return a unique
407  * hash for these particular properties. RenderAttribs that compare the same
408  * with compare_to_impl(), above, should return the same hash; RenderAttribs
409  * that compare differently should return a different hash.
410  */
411 size_t RenderAttrib::
412 get_hash_impl() const {
413  return 0;
414 }
415 
416 /**
417  * Intended to be overridden by derived RenderAttrib types to specify how two
418  * consecutive RenderAttrib objects of the same type interact.
419  *
420  * This should return the result of applying the other RenderAttrib to a node
421  * in the scene graph below this RenderAttrib, which was already applied. In
422  * most cases, the result is the same as the other RenderAttrib (that is, a
423  * subsequent RenderAttrib completely replaces the preceding one). On the
424  * other hand, some kinds of RenderAttrib (for instance, ColorTransformAttrib)
425  * might combine in meaningful ways.
426  */
427 CPT(RenderAttrib) RenderAttrib::
428 compose_impl(const RenderAttrib *other) const {
429  return other;
430 }
431 
432 /**
433  * Intended to be overridden by derived RenderAttrib types to specify how two
434  * consecutive RenderAttrib objects of the same type interact.
435  *
436  * See invert_compose() and compose_impl().
437  */
438 CPT(RenderAttrib) RenderAttrib::
439 invert_compose_impl(const RenderAttrib *other) const {
440  return other;
441 }
442 
443 /**
444  * Outputs a string representation of the given PandaCompareFunc object.
445  */
446 void RenderAttrib::
447 output_comparefunc(ostream &out, PandaCompareFunc fn) const {
448  switch (fn) {
449  case M_none:
450  out << "none";
451  break;
452 
453  case M_never:
454  out << "never";
455  break;
456 
457  case M_less:
458  out << "less";
459  break;
460 
461  case M_equal:
462  out << "equal";
463  break;
464 
465  case M_less_equal:
466  out << "less_equal";
467  break;
468 
469  case M_greater:
470  out << "greater";
471  break;
472 
473  case M_not_equal:
474  out << "not_equal";
475  break;
476 
477  case M_greater_equal:
478  out << "greater_equal";
479  break;
480 
481  case M_always:
482  out << "always";
483  break;
484  }
485 }
486 
487 /**
488  * This inverse of return_new, this releases this object from the global
489  * RenderAttrib table.
490  *
491  * You must already be holding _attribs_lock before you call this method.
492  */
493 void RenderAttrib::
494 release_new() {
495  nassertv(_attribs_lock->debug_is_locked());
496 
497  if (_saved_entry != -1) {
498  _saved_entry = -1;
499  nassertv_always(_attribs->remove(this));
500  }
501 }
502 
503 /**
504  * Make sure the global _attribs map is allocated. This only has to be done
505  * once. We could make this map static, but then we run into problems if
506  * anyone creates a RenderAttrib object at static init time; it also seems to
507  * cause problems when the Panda shared library is unloaded at application
508  * exit time.
509  */
511 init_attribs() {
512  _attribs = new Attribs;
513 
514  // TODO: we should have a global Panda mutex to allow us to safely create
515  // _attribs_lock without a startup race condition. For the meantime, this
516  // is OK because we guarantee that this method is called at static init
517  // time, presumably when there is still only one thread in the world.
518  _attribs_lock = new LightReMutex("RenderAttrib::_attribs_lock");
520 }
521 
522 /**
523  * Writes the contents of this object to the datagram for shipping out to a
524  * Bam file.
525  */
527 write_datagram(BamWriter *manager, Datagram &dg) {
528  TypedWritable::write_datagram(manager, dg);
529 }
530 
531 /**
532  * Called immediately after complete_pointers(), this gives the object a
533  * chance to adjust its own pointer if desired. Most objects don't change
534  * pointers after completion, but some need to.
535  *
536  * Once this function has been called, the old pointer will no longer be
537  * accessed.
538  */
540 change_this(TypedWritable *old_ptr, BamReader *manager) {
541  // First, uniquify the pointer.
542  RenderAttrib *attrib = DCAST(RenderAttrib, old_ptr);
543  CPT(RenderAttrib) pointer = return_unique(attrib);
544 
545  // But now we have a problem, since we have to hold the reference count and
546  // there's no way to return a TypedWritable while still holding the
547  // reference count! We work around this by explicitly upping the count, and
548  // also setting a finalize() callback to down it later.
549  if (pointer == attrib) {
550  pointer->ref();
551  manager->register_finalize(attrib);
552  }
553 
554  // We have to cast the pointer back to non-const, because the bam reader
555  // expects that.
556  return (RenderAttrib *)pointer.p();
557 }
558 
559 /**
560  * Called by the BamReader to perform any final actions needed for setting up
561  * the object after all objects have been read and all pointers have been
562  * completed.
563  */
565 finalize(BamReader *) {
566  // Unref the pointer that we explicitly reffed in change_this().
567  unref();
568 
569  // We should never get back to zero after unreffing our own count, because
570  // we expect to have been stored in a pointer somewhere. If we do get to
571  // zero, it's a memory leak; the way to avoid this is to call unref_delete()
572  // above instead of unref(), but this is dangerous to do from within a
573  // virtual function.
574  nassertv(get_ref_count() != 0);
575 }
576 
577 /**
578  * This internal function is called by make_from_bam to read in all of the
579  * relevant data from the BamFile for the new RenderAttrib.
580  */
581 void RenderAttrib::
582 fillin(DatagramIterator &scan, BamReader *manager) {
583  TypedWritable::fillin(scan, manager);
584  manager->register_change_this(change_this, this);
585 }
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
RenderAttrib::lower_attrib_can_override
virtual bool lower_attrib_can_override() const
Intended to be overridden by derived RenderAttrib types to specify how two consecutive RenderAttrib o...
Definition: renderAttrib.cxx:73
Thread::get_main_thread
get_main_thread
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process.
Definition: thread.h:107
RenderAttrib::unref
virtual bool unref() const final
This method overrides ReferenceCount::unref() to clear the pointer from the global object pool when i...
Definition: renderAttrib.cxx:106
ReferenceCount::unref_if_one
bool unref_if_one() const
Atomically decreases the reference count of this object if it is one.
Definition: referenceCount.I:327
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
RenderAttrib::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: renderAttrib.cxx:527
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SimpleHashMap::remove
bool remove(const Key &key)
Removes the indicated key and its associated data from the table.
Definition: simpleHashMap.I:275
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
CPT
CPT(RenderAttrib) RenderAttrib
This function is used by derived RenderAttrib types to share a common RenderAttrib pointer for all eq...
Definition: renderAttrib.cxx:320
renderAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
RenderAttrib
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
SimpleHashMap::get_key
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
Definition: simpleHashMap.I:396
RenderAttrib::finalize
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: renderAttrib.cxx:565
BamReader::register_change_this
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
Definition: bamReader.cxx:835
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SimpleHashMap::validate
bool validate() const
Returns true if the internal table appears to be consistent, false if there are some internal errors.
Definition: simpleHashMap.I:525
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
SimpleHashMap
This template class implements an unordered map of keys to data, implemented as a hashtable.
Definition: simpleHashMap.h:81
RenderAttrib::get_num_attribs
static int get_num_attribs()
Returns the total number of unique RenderAttrib objects allocated in the world.
Definition: renderAttrib.cxx:157
RenderAttrib::has_cull_callback
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined.
Definition: renderAttrib.cxx:83
Thread::get_current_thread
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
RenderAttrib::list_attribs
static void list_attribs(std::ostream &out)
Lists all of the RenderAttribs in the cache to the output stream, one per line.
Definition: renderAttrib.cxx:172
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
BamReader::register_finalize
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
SimpleHashMap::find
int find(const Key &key) const
Searches for the indicated key in the table.
Definition: simpleHashMap.I:177
LightReMutexDirect::debug_is_locked
bool debug_is_locked() const
Returns true if the current thread has locked the LightReMutex, false otherwise.
Definition: lightReMutexDirect.I:123
RenderAttrib::~RenderAttrib
virtual ~RenderAttrib()
The destructor is responsible for removing the RenderAttrib from the global set if it is there.
Definition: renderAttrib.cxx:47
RenderAttrib::init_attribs
static void init_attribs()
Make sure the global _attribs map is allocated.
Definition: renderAttrib.cxx:511
TypedWritable::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: typedWritable.cxx:54
RenderAttrib::cull_callback
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const
If has_cull_callback() returns true, this function will be called during the cull traversal to perfor...
Definition: renderAttrib.cxx:97
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
SimpleHashMap::store
int store(const Key &key, const Value &data)
Records the indicated key/data pair in the map.
Definition: simpleHashMap.I:198
RenderAttrib::garbage_collect
static int garbage_collect()
Performs a garbage-collection cycle.
Definition: renderAttrib.cxx:188
ReferenceCount::ref
void ref() const
Explicitly increments the reference count.
Definition: referenceCount.I:151
SimpleHashMap::is_empty
bool is_empty() const
Returns true if the table is empty; i.e.
Definition: simpleHashMap.I:475
ReferenceCount::unref
virtual bool unref() const
Explicitly decrements the reference count.
Definition: referenceCount.I:179
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable::fillin
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
Definition: typedWritable.cxx:103
LightReMutex
A lightweight reentrant mutex.
Definition: lightReMutex.h:32
config_pgraph.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderAttrib::change_this
static TypedWritable * change_this(TypedWritable *old_ptr, BamReader *manager)
Called immediately after complete_pointers(), this gives the object a chance to adjust its own pointe...
Definition: renderAttrib.cxx:540
ReferenceCount::get_ref_count
get_ref_count
Returns the current reference count.
Definition: referenceCount.h:53
SimpleHashMap::get_num_entries
size_t get_num_entries() const
Returns the number of active entries in the table.
Definition: simpleHashMap.I:466
SimpleHashMap::consider_shrink_table
bool consider_shrink_table()
Shrinks the table if the allocated storage is significantly larger than the number of elements in it.
Definition: simpleHashMap.I:714
lightReMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderAttrib::validate_attribs
static bool validate_attribs()
Ensures that the cache is still stored in sorted order.
Definition: renderAttrib.cxx:261