diff --git a/panda/src/express/pointerToBase.I b/panda/src/express/pointerToBase.I index c016b263a8..b66f8a816a 100644 --- a/panda/src/express/pointerToBase.I +++ b/panda/src/express/pointerToBase.I @@ -105,209 +105,6 @@ reassign(const PointerToBase ©) { reassign((To *)copy._void_ptr); } -#ifndef CPPPARSER -#ifndef WIN32_VC -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Equivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator == (const To *other) const { - return (To *)_void_ptr == other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Nonequivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator != (const To *other) const { - return (To *)_void_ptr != other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator > (const To *other) const { - return (To *)_void_ptr > other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Less-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator <= (const To *other) const { - return (To *)_void_ptr <= other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator >= (const To *other) const { - return (To *)_void_ptr >= other; -} -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Equivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator == (To *other) const { - return (To *)_void_ptr == other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Nonequivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator != (To *other) const { - return (To *)_void_ptr != other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator > (To *other) const { - return (To *)_void_ptr > other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Less-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator <= (To *other) const { - return (To *)_void_ptr <= other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator >= (To *other) const { - return (To *)_void_ptr >= other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Equivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator == (const PointerToBase &other) const { - return (To *)_void_ptr == (To *)other._void_ptr; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Nonequivalence operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator != (const PointerToBase &other) const { - return (To *)_void_ptr != (To *)other._void_ptr; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator > (const PointerToBase &other) const { - return (To *)_void_ptr > (To *)other._void_ptr; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Less-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator <= (const PointerToBase &other) const { - return (To *)_void_ptr <= (To *)other._void_ptr; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Greater-than-or-equal operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator >= (const PointerToBase &other) const { - return (To *)_void_ptr >= (To *)other._void_ptr; -} -#endif // WIN32_VC - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Less-than operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator < (const To *other) const { - return (To *)_void_ptr < other; -} - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::Less-than operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE bool PointerToBase:: -operator < (const PointerToBase &other) const { - return (To *)_void_ptr < (To *)other._void_ptr; -} - -#endif // CPPPARSER - -//////////////////////////////////////////////////////////////////// -// Function: PointerToBase::get_hash -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -template -INLINE size_t PointerToBase:: -get_hash() const { - return (size_t)_void_ptr; -} - - //////////////////////////////////////////////////////////////////// // Function: PointerToBase::clear diff --git a/panda/src/express/pointerToBase.h b/panda/src/express/pointerToBase.h index 082a563a83..854d1afac2 100644 --- a/panda/src/express/pointerToBase.h +++ b/panda/src/express/pointerToBase.h @@ -49,33 +49,6 @@ protected: // PointerToBase, because we will have to specialize on const // vs. non-const later. -public: - // These comparison functions are common to all things PointerTo, so - // they're defined up here. -#ifndef CPPPARSER -#ifndef WIN32_VC - INLINE bool operator == (const To *other) const; - INLINE bool operator != (const To *other) const; - INLINE bool operator > (const To *other) const; - INLINE bool operator <= (const To *other) const; - INLINE bool operator >= (const To *other) const; - INLINE bool operator == (To *other) const; - INLINE bool operator != (To *other) const; - INLINE bool operator > (To *other) const; - INLINE bool operator <= (To *other) const; - INLINE bool operator >= (To *other) const; - - INLINE bool operator == (const PointerToBase &other) const; - INLINE bool operator != (const PointerToBase &other) const; - INLINE bool operator > (const PointerToBase &other) const; - INLINE bool operator <= (const PointerToBase &other) const; - INLINE bool operator >= (const PointerToBase &other) const; -#endif // WIN32_VC - INLINE bool operator < (const To *other) const; - INLINE bool operator < (const PointerToBase &other) const; -#endif // CPPPARSER - INLINE size_t get_hash() const; - PUBLISHED: INLINE void clear(); diff --git a/panda/src/express/pointerToVoid.I b/panda/src/express/pointerToVoid.I index f15f068bd0..81dbf97630 100644 --- a/panda/src/express/pointerToVoid.I +++ b/panda/src/express/pointerToVoid.I @@ -48,3 +48,185 @@ INLINE bool PointerToVoid:: is_null() const { return (_void_ptr == (void *)NULL); } + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::get_hash +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE size_t PointerToVoid:: +get_hash() const { + return (size_t)_void_ptr; +} + +#ifndef WIN32_VC +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Equivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator == (const void *other) const { + return _void_ptr == other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Nonequivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator != (const void *other) const { + return _void_ptr != other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator > (const void *other) const { + return _void_ptr > other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Less-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator <= (const void *other) const { + return _void_ptr <= other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator >= (const void *other) const { + return _void_ptr >= other; +} +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Equivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator == (void *other) const { + return _void_ptr == other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Nonequivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator != (void *other) const { + return _void_ptr != other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator > (void *other) const { + return _void_ptr > other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Less-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator <= (void *other) const { + return _void_ptr <= other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator >= (void *other) const { + return _void_ptr >= other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Equivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator == (const PointerToVoid &other) const { + return _void_ptr == other._void_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Nonequivalence operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator != (const PointerToVoid &other) const { + return _void_ptr != other._void_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator > (const PointerToVoid &other) const { + return _void_ptr > other._void_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Less-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator <= (const PointerToVoid &other) const { + return _void_ptr <= other._void_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Greater-than-or-equal operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator >= (const PointerToVoid &other) const { + return _void_ptr >= other._void_ptr; +} +#endif // WIN32_VC + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Less-than operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator < (const void *other) const { + return _void_ptr < other; +} + +//////////////////////////////////////////////////////////////////// +// Function: PointerToVoid::Less-than operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool PointerToVoid:: +operator < (const PointerToVoid &other) const { + return _void_ptr < other._void_ptr; +} + diff --git a/panda/src/express/pointerToVoid.h b/panda/src/express/pointerToVoid.h index 98bce14b45..4aecc12569 100644 --- a/panda/src/express/pointerToVoid.h +++ b/panda/src/express/pointerToVoid.h @@ -40,6 +40,31 @@ protected: PUBLISHED: INLINE bool is_null() const; + INLINE size_t get_hash() const; + +public: + // These comparison functions are common to all things PointerTo, so + // they're defined up here. +#ifndef WIN32_VC + INLINE bool operator == (const void *other) const; + INLINE bool operator != (const void *other) const; + INLINE bool operator > (const void *other) const; + INLINE bool operator <= (const void *other) const; + INLINE bool operator >= (const void *other) const; + INLINE bool operator == (void *other) const; + INLINE bool operator != (void *other) const; + INLINE bool operator > (void *other) const; + INLINE bool operator <= (void *other) const; + INLINE bool operator >= (void *other) const; + + INLINE bool operator == (const PointerToVoid &other) const; + INLINE bool operator != (const PointerToVoid &other) const; + INLINE bool operator > (const PointerToVoid &other) const; + INLINE bool operator <= (const PointerToVoid &other) const; + INLINE bool operator >= (const PointerToVoid &other) const; +#endif // WIN32_VC + INLINE bool operator < (const void *other) const; + INLINE bool operator < (const PointerToVoid &other) const; protected: // Within the PointerToVoid class, we only store a void pointer. diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index f7277661f2..787d4d25fb 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -37,6 +37,7 @@ #include "luse.h" #include "ordered_vector.h" #include "pointerTo.h" +#include "nodePointerTo.h" #include "pointerToArray.h" #include "notify.h" @@ -315,10 +316,10 @@ private: Up _up; Paths _paths; - CPT(RenderState) _state; + NCPT(RenderState) _state; CPT(RenderEffects) _effects; - CPT(TransformState) _transform; - CPT(TransformState) _prev_transform; + NCPT(TransformState) _transform; + NCPT(TransformState) _prev_transform; TagData _tag_data; diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 6e069d429d..ca86c0e796 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -61,6 +61,74 @@ get_override(int n) const { return _attributes[n]._override; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::cache_ref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int RenderState:: +cache_ref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::cache_ref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::cache_ref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::cache_unref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int RenderState:: +cache_unref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::cache_unref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::cache_unref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::node_ref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int RenderState:: +node_ref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::node_ref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::node_ref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::node_unref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int RenderState:: +node_unref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::node_unref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::node_unref(); +#endif // DO_PSTATS +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::get_draw_order // Access: Published @@ -325,6 +393,20 @@ is_destructing() const { #endif } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::consider_update_pstats +// Access: Private +// Description: Calls update_pstats() if the state of the referenced +// bits has changed from the indicated value. +//////////////////////////////////////////////////////////////////// +INLINE void RenderState:: +consider_update_pstats(int old_referenced_bits) const { + int new_referenced_bits = get_referenced_bits(); + if (old_referenced_bits != new_referenced_bits) { + update_pstats(old_referenced_bits, new_referenced_bits); + } +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::Composition::Constructor // Access: Public diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index aa2e0a4931..5470f8959f 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -40,6 +40,8 @@ UpdateSeq RenderState::_last_cycle_detect; PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update"); PStatCollector RenderState::_state_compose_pcollector("*:State Cache:Compose State"); PStatCollector RenderState::_state_invert_pcollector("*:State Cache:Invert State"); +PStatCollector RenderState::_node_counter("RenderStates:On nodes"); +PStatCollector RenderState::_cache_counter("RenderStates:Cached"); TypeHandle RenderState::_type_handle; @@ -1611,6 +1613,29 @@ determine_render_mode() { _flags |= F_checked_render_mode; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::update_pstats +// Access: Private +// Description: Moves the RenderState object from one PStats category +// to another, so that we can track in PStats how many +// pointers are held by nodes, and how many are held in +// the cache only. +//////////////////////////////////////////////////////////////////// +void RenderState:: +update_pstats(int old_referenced_bits, int new_referenced_bits) { + if ((old_referenced_bits & R_node) != 0) { + _node_counter.sub_level(1); + } else if ((old_referenced_bits & R_cache) != 0) { + _cache_counter.sub_level(1); + } + if ((new_referenced_bits & R_node) != 0) { + _node_counter.add_level(1); + } else if ((new_referenced_bits & R_cache) != 0) { + _cache_counter.add_level(1); + } +} + + //////////////////////////////////////////////////////////////////// // Function: RenderState::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 2504f0bc6b..b6ea75c7de 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -22,7 +22,7 @@ #include "pandabase.h" #include "renderAttrib.h" -#include "cachedTypedWritableReferenceCount.h" +#include "nodeCachedReferenceCount.h" #include "pointerTo.h" #include "ordered_vector.h" #include "updateSeq.h" @@ -52,7 +52,7 @@ class FactoryParams; // instead of modifying a RenderState object, create a // new one. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA RenderState : public CachedTypedWritableReferenceCount { +class EXPCL_PANDA RenderState : public NodeCachedReferenceCount { protected: RenderState(); @@ -100,6 +100,11 @@ PUBLISHED: int unref() const; + INLINE int cache_ref() const; + INLINE int cache_unref() const; + INLINE int node_ref() const; + INLINE int node_unref() const; + void output(ostream &out) const; void write(ostream &out, int indent_level) const; @@ -174,6 +179,9 @@ private: INLINE void set_destructing(); INLINE bool is_destructing() const; + INLINE void consider_update_pstats(int old_referenced_bits) const; + static void update_pstats(int old_referenced_bits, int new_referenced_bits); + private: typedef pset > States; static States *_states; @@ -215,6 +223,9 @@ private: static PStatCollector _state_compose_pcollector; static PStatCollector _state_invert_pcollector; + static PStatCollector _node_counter; + static PStatCollector _cache_counter; + private: // This is the actual data within the RenderState: a set of // RenderAttribs. @@ -283,9 +294,9 @@ public: return _type_handle; } static void init_type() { - CachedTypedWritableReferenceCount::init_type(); + NodeCachedReferenceCount::init_type(); register_type(_type_handle, "RenderState", - CachedTypedWritableReferenceCount::get_class_type()); + NodeCachedReferenceCount::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pgraph/stateMunger.h b/panda/src/pgraph/stateMunger.h index beadedf6d9..452a6d9a12 100644 --- a/panda/src/pgraph/stateMunger.h +++ b/panda/src/pgraph/stateMunger.h @@ -21,6 +21,7 @@ #include "pandabase.h" #include "qpgeomMunger.h" +#include "renderState.h" //////////////////////////////////////////////////////////////////// // Class : StateMunger diff --git a/panda/src/pgraph/transformState.I b/panda/src/pgraph/transformState.I index 66e53d7c42..60a653c9a0 100644 --- a/panda/src/pgraph/transformState.I +++ b/panda/src/pgraph/transformState.I @@ -437,6 +437,74 @@ get_mat() const { return _mat; } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::cache_ref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int TransformState:: +cache_ref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::cache_ref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::cache_ref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::cache_unref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int TransformState:: +cache_unref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::cache_unref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::cache_unref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::node_ref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int TransformState:: +node_ref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::node_ref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::node_ref(); +#endif // DO_PSTATS +} + +//////////////////////////////////////////////////////////////////// +// Function: TransformState::node_unref +// Access: Published +// Description: Overrides this method to update PStats appropriately. +//////////////////////////////////////////////////////////////////// +INLINE int TransformState:: +node_unref() const { +#ifdef DO_PSTATS + int old_referenced_bits = get_referenced_bits(); + int result = NodeCachedReferenceCount::node_unref(); + consider_update_pstats(old_referenced_bits); + return result; +#else // DO_PSTATS + return NodeCachedReferenceCount::node_unref(); +#endif // DO_PSTATS +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::check_singular // Access: Private @@ -563,6 +631,20 @@ is_destructing() const { #endif } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::consider_update_pstats +// Access: Private +// Description: Calls update_pstats() if the state of the referenced +// bits has changed from the indicated value. +//////////////////////////////////////////////////////////////////// +INLINE void TransformState:: +consider_update_pstats(int old_referenced_bits) const { + int new_referenced_bits = get_referenced_bits(); + if (old_referenced_bits != new_referenced_bits) { + update_pstats(old_referenced_bits, new_referenced_bits); + } +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::Composition::Constructor // Access: Public diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 25b0b2fa50..89a0e1589d 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -32,6 +32,8 @@ UpdateSeq TransformState::_last_cycle_detect; PStatCollector TransformState::_cache_update_pcollector("*:State Cache:Update"); PStatCollector TransformState::_transform_compose_pcollector("*:State Cache:Compose Transform"); PStatCollector TransformState::_transform_invert_pcollector("*:State Cache:Invert Transform"); +PStatCollector TransformState::_node_counter("TransformStates:On nodes"); +PStatCollector TransformState::_cache_counter("TransformStates:Cached"); TypeHandle TransformState::_type_handle; @@ -1500,6 +1502,28 @@ calc_mat() { _flags |= F_mat_known; } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::update_pstats +// Access: Private +// Description: Moves the TransformState object from one PStats category +// to another, so that we can track in PStats how many +// pointers are held by nodes, and how many are held in +// the cache only. +//////////////////////////////////////////////////////////////////// +void TransformState:: +update_pstats(int old_referenced_bits, int new_referenced_bits) { + if ((old_referenced_bits & R_node) != 0) { + _node_counter.sub_level(1); + } else if ((old_referenced_bits & R_cache) != 0) { + _cache_counter.sub_level(1); + } + if ((new_referenced_bits & R_node) != 0) { + _node_counter.add_level(1); + } else if ((new_referenced_bits & R_cache) != 0) { + _cache_counter.add_level(1); + } +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 3beeed188a..c61e4146a6 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -21,7 +21,7 @@ #include "pandabase.h" -#include "cachedTypedWritableReferenceCount.h" +#include "nodeCachedReferenceCount.h" #include "pointerTo.h" #include "luse.h" #include "pset.h" @@ -54,7 +54,7 @@ class FactoryParams; // instead of modifying a TransformState object, create a // new one. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA TransformState : public CachedTypedWritableReferenceCount { +class EXPCL_PANDA TransformState : public NodeCachedReferenceCount { protected: TransformState(); @@ -129,6 +129,11 @@ PUBLISHED: int unref() const; + INLINE int cache_ref() const; + INLINE int cache_unref() const; + INLINE int node_ref() const; + INLINE int node_unref() const; + void output(ostream &out) const; void write(ostream &out, int indent_level) const; @@ -203,6 +208,9 @@ private: static PStatCollector _transform_compose_pcollector; static PStatCollector _transform_invert_pcollector; + static PStatCollector _node_counter; + static PStatCollector _cache_counter; + private: // This is the actual data within the TransformState. INLINE void check_singular() const; @@ -221,6 +229,9 @@ private: INLINE void set_destructing(); INLINE bool is_destructing() const; + INLINE void consider_update_pstats(int old_referenced_bits) const; + static void update_pstats(int old_referenced_bits, int new_referenced_bits); + enum Flags { F_is_identity = 0x0001, F_is_singular = 0x0002, @@ -260,9 +271,9 @@ public: return _type_handle; } static void init_type() { - CachedTypedWritableReferenceCount::init_type(); + NodeCachedReferenceCount::init_type(); register_type(_type_handle, "TransformState", - CachedTypedWritableReferenceCount::get_class_type()); + NodeCachedReferenceCount::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index 097139a0f4..ba4c518953 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -202,8 +202,12 @@ static LevelCollectorProperties level_properties[] = { { 1, "Memory usage:C++", { 0.2, 0.2, 1.0 } }, { 1, "Memory usage:Interpreter", { 0.8, 0.2, 0.5 } }, { 1, "TransformStates", { 1.0, 0.5, 0.5 }, "", 5000 }, + { 1, "TransformStates:On nodes", { 0.2, 0.8, 1.0 } }, + { 1, "TransformStates:Cached", { 1.0, 0.0, 0.2 } }, { 1, "TransformStates:Unused", { 0.2, 0.2, 0.2 } }, { 1, "RenderStates", { 0.5, 0.5, 1.0 }, "", 1000 }, + { 1, "RenderStates:On nodes", { 0.2, 0.8, 1.0 } }, + { 1, "RenderStates:Cached", { 1.0, 0.0, 0.2 } }, { 1, "RenderStates:Unused", { 0.2, 0.2, 0.2 } }, { 0, NULL } }; diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 7ee19ce04d..7f2f5dc8e9 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -39,6 +39,9 @@ load_prc_file.h \ modifierButtons.I modifierButtons.h mouseButton.h \ mouseData.I mouseData.h nameUniquifier.I nameUniquifier.h \ + nodeCachedReferenceCount.h nodeCachedReferenceCount.I \ + nodePointerToBase.h nodePointerToBase.I \ + nodePointerTo.h nodePointerTo.I \ pipeline.h pipeline.I \ pipelineCycler.h pipelineCycler.I \ pipelineCyclerBase.h pipelineCyclerBase.I \ @@ -71,6 +74,9 @@ load_prc_file.cxx \ modifierButtons.cxx mouseButton.cxx mouseData.cxx \ nameUniquifier.cxx \ + nodeCachedReferenceCount.cxx \ + nodePointerToBase.cxx \ + nodePointerTo.cxx \ pipeline.cxx \ pipelineCycler.cxx \ pipelineCyclerBase.cxx \ @@ -114,6 +120,9 @@ modifierButtons.I \ modifierButtons.h mouseButton.h mouseData.I mouseData.h \ nameUniquifier.I nameUniquifier.h \ + nodeCachedReferenceCount.h nodeCachedReferenceCount.I \ + nodePointerToBase.h nodePointerToBase.I \ + nodePointerTo.h nodePointerTo.I \ pipeline.h pipeline.I \ pipelineCycler.h pipelineCycler.I \ pipelineCyclerBase.h pipelineCyclerBase.I \ diff --git a/panda/src/putil/cachedTypedWritableReferenceCount.I b/panda/src/putil/cachedTypedWritableReferenceCount.I index 2e72403387..fe650eb839 100644 --- a/panda/src/putil/cachedTypedWritableReferenceCount.I +++ b/panda/src/putil/cachedTypedWritableReferenceCount.I @@ -130,20 +130,20 @@ INLINE CachedTypedWritableReferenceCount:: //////////////////////////////////////////////////////////////////// // Function: CachedTypedWritableReferenceCount::get_cache_ref_count -// Access: Public +// Access: Published // Description: Returns the current reference count. //////////////////////////////////////////////////////////////////// INLINE int CachedTypedWritableReferenceCount:: get_cache_ref_count() const { #ifndef NDEBUG - test_cache_ref_count_integrity(); + test_ref_count_integrity(); #endif return _cache_ref_count; } //////////////////////////////////////////////////////////////////// // Function: CachedTypedWritableReferenceCount::cache_ref -// Access: Public +// Access: Published // Description: Explicitly increments the reference count. // // This function is const, even though it changes the @@ -179,7 +179,7 @@ cache_ref() const { //////////////////////////////////////////////////////////////////// // Function: CachedTypedWritableReferenceCount::cache_unref -// Access: Public +// Access: Published // Description: Explicitly decrements the reference count. Note that // the object will not be implicitly deleted by unref() // simply because the reference count drops to zero. @@ -231,13 +231,13 @@ cache_unref() const { //////////////////////////////////////////////////////////////////// -// Function: CachedTypedWritableReferenceCount::test_cache_ref_count_integrity -// Access: Public +// Function: CachedTypedWritableReferenceCount::test_ref_count_integrity +// Access: Published // Description: Does some easy checks to make sure that the reference // count isn't completely bogus. //////////////////////////////////////////////////////////////////// INLINE void CachedTypedWritableReferenceCount:: -test_cache_ref_count_integrity() const { +test_ref_count_integrity() const { #ifndef NDEBUG nassertv(this != NULL); @@ -255,7 +255,7 @@ test_cache_ref_count_integrity() const { // somewhere. nassertv(_cache_ref_count >= 0); - test_ref_count_integrity(); + TypedWritableReferenceCount::test_ref_count_integrity(); #endif } diff --git a/panda/src/putil/cachedTypedWritableReferenceCount.h b/panda/src/putil/cachedTypedWritableReferenceCount.h index 7e7db7612d..f2c87a6e9d 100644 --- a/panda/src/putil/cachedTypedWritableReferenceCount.h +++ b/panda/src/putil/cachedTypedWritableReferenceCount.h @@ -52,7 +52,7 @@ PUBLISHED: INLINE int get_cache_ref_count() const; INLINE int cache_ref() const; INLINE int cache_unref() const; - INLINE void test_cache_ref_count_integrity() const; + INLINE void test_ref_count_integrity() const; private: int _cache_ref_count; diff --git a/panda/src/putil/config_util.cxx b/panda/src/putil/config_util.cxx index c9556d7f1e..8667b1359b 100644 --- a/panda/src/putil/config_util.cxx +++ b/panda/src/putil/config_util.cxx @@ -24,6 +24,7 @@ #include "datagram.h" #include "factoryParam.h" #include "namable.h" +#include "nodeCachedReferenceCount.h" #include "referenceCount.h" #include "typedObject.h" #include "typedReferenceCount.h" @@ -63,6 +64,7 @@ ConfigureFn(config_util) { Datagram::init_type(); FactoryParam::init_type(); Namable::init_type(); + NodeCachedReferenceCount::init_type(); ReferenceCount::init_type(); TypedObject::init_type(); TypedReferenceCount::init_type(); diff --git a/panda/src/putil/nodeCachedReferenceCount.I b/panda/src/putil/nodeCachedReferenceCount.I new file mode 100644 index 0000000000..55763dde86 --- /dev/null +++ b/panda/src/putil/nodeCachedReferenceCount.I @@ -0,0 +1,319 @@ +// Filename: nodeCachedReferenceCount.I +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::Constructor +// Access: Protected +// Description: The ReferenceCount constructor is protected because +// you almost never want to create just a ReferenceCount +// object by itself, and it's probably a mistake if you +// try. +// +// ReferenceCount doesn't store any useful information +// in its own right; its only purpose is to add +// reference-counting to some other class via +// inheritance. +//////////////////////////////////////////////////////////////////// +INLINE NodeCachedReferenceCount:: +NodeCachedReferenceCount() { + _node_ref_count = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::Copy Constructor +// Access: Protected +// Description: The copies of reference-counted objects do not +// themselves inherit the reference count! +// +// This copy constructor is protected because you almost +// never want to create just a ReferenceCount object by +// itself, and it's probably a mistake if you try. +//////////////////////////////////////////////////////////////////// +INLINE NodeCachedReferenceCount:: +NodeCachedReferenceCount(const NodeCachedReferenceCount ©) : CachedTypedWritableReferenceCount(copy) { + _node_ref_count = 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::Copy Assignment Operator +// Access: Protected +// Description: The copies of reference-counted objects do not +// themselves inherit the reference count! +// +// This copy assignment operator is protected because +// you almost never want to copy just a ReferenceCount +// object by itself, and it's probably a mistake if you +// try. Instead, this should only be called from a +// derived class that implements this operator and then +// calls up the inheritance chain. +//////////////////////////////////////////////////////////////////// +INLINE void NodeCachedReferenceCount:: +operator = (const NodeCachedReferenceCount ©) { + nassertv(this != NULL); + + // If this assertion fails, our own pointer was recently deleted. + // Possibly you used a real pointer instead of a PointerTo at some + // point, and the object was deleted when the PointerTo went out of + // scope. Maybe you tried to create an automatic (local variable) + // instance of a class that derives from ReferenceCount. Or maybe + // your headers are out of sync, and you need to make clean in + // direct or some higher tree. + nassertv(_node_ref_count != -100); + + CachedTypedWritableReferenceCount::operator = (copy); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::Destructor +// Access: Protected +// Description: The ReferenceCount destructor is protected to +// discourage users from accidentally trying to delete a +// ReferenceCount pointer directly. This is almost +// always a bad idea, since the destructor is not +// virtual, and you've almost certainly got some pointer +// to something that inherits from ReferenceCount, not +// just a plain old ReferenceCount object. +//////////////////////////////////////////////////////////////////// +INLINE NodeCachedReferenceCount:: +~NodeCachedReferenceCount() { + nassertv(this != NULL); + + // If this assertion fails, we're trying to delete an object that + // was just deleted. Possibly you used a real pointer instead of a + // PointerTo at some point, and the object was deleted when the + // PointerTo went out of scope. Maybe you tried to create an + // automatic (local variable) instance of a class that derives from + // ReferenceCount. Or maybe your headers are out of sync, and you + // need to make clean in direct or some higher tree. + nassertv(_node_ref_count != -100); + + // If this assertion fails, the reference counts are all screwed + // up altogether. Maybe some errant code stomped all over memory + // somewhere. + nassertv(_node_ref_count >= 0); + + // If this assertion fails, someone tried to delete this object + // while its reference count was still positive. Maybe you tried + // to point a PointerTo at a static object (a local variable, + // instead of one allocated via new)? The test below against 0x7f + // is supposed to check for that, but it's a pretty hokey test. + + // Another possibility is you inadvertently omitted a copy + // constructor for a ReferenceCount object, and then bitwise + // copied a dynamically allocated value--reference count and + // all--onto a locally allocated one. + nassertv(_node_ref_count == 0); + +#ifndef NDEBUG + // Ok, all clear to delete. Now set the reference count to -100, + // so we'll have a better chance of noticing if we happen to have + // a stray pointer to it still out there. + _node_ref_count = -100; +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::get_node_ref_count +// Access: Published +// Description: Returns the current reference count. +//////////////////////////////////////////////////////////////////// +INLINE int NodeCachedReferenceCount:: +get_node_ref_count() const { +#ifndef NDEBUG + test_ref_count_integrity(); +#endif + return _node_ref_count; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::node_ref +// Access: Published +// Description: Explicitly increments the reference count. +// +// This function is const, even though it changes the +// object, because generally fiddling with an object's +// reference count isn't considered part of fiddling +// with the object. An object might be const in other +// ways, but we still need to accurately count the +// number of references to it. +// +// The return value is the new reference count. +//////////////////////////////////////////////////////////////////// +INLINE int NodeCachedReferenceCount:: +node_ref() const { + nassertr(this != NULL, 0); + + // If this assertion fails, we're trying to delete an object that + // was just deleted. Possibly you used a real pointer instead of a + // PointerTo at some point, and the object was deleted when the + // PointerTo went out of scope. Maybe you tried to create an + // automatic (local variable) instance of a class that derives from + // ReferenceCount. Or maybe your headers are out of sync, and you + // need to make clean in direct or some higher tree. + nassertr(_node_ref_count != -100, 0); + + // If this assertion fails, the reference counts are all screwed + // up altogether. Maybe some errant code stomped all over memory + // somewhere. + nassertr(_node_ref_count >= 0, 0); + + ref(); + return AtomicAdjust::inc(((NodeCachedReferenceCount *)this)->_node_ref_count); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::node_unref +// Access: Published +// Description: Explicitly decrements the reference count. Note that +// the object will not be implicitly deleted by unref() +// simply because the reference count drops to zero. +// (Having a member function delete itself is +// problematic; plus, we don't have a virtual destructor +// anyway.) However, see the helper function +// unref_delete(). +// +// User code should avoid using ref() and unref() +// directly, which can result in missed reference +// counts. Instead, let a PointerTo object manage the +// reference counting automatically. +// +// This function is const, even though it changes the +// object, because generally fiddling with an object's +// reference count isn't considered part of fiddling +// with the object. An object might be const in other +// ways, but we still need to accurately count the +// number of references to it. +// +// The return value is the new reference count. +//////////////////////////////////////////////////////////////////// +INLINE int NodeCachedReferenceCount:: +node_unref() const { + nassertr(this != NULL, false); + + // If this assertion fails, we're trying to delete an object that + // was just deleted. Possibly you used a real pointer instead of a + // PointerTo at some point, and the object was deleted when the + // PointerTo went out of scope. Maybe you tried to create an + // automatic (local variable) instance of a class that derives from + // ReferenceCount. Or maybe your headers are out of sync, and you + // need to make clean in direct or some higher tree. + nassertr(_node_ref_count != -100, false); + + // If this assertion fails, the reference counts are all screwed + // up altogether. Maybe some errant code stomped all over memory + // somewhere. + nassertr(_node_ref_count >= 0, false); + + // If this assertion fails, you tried to unref an object with a + // zero reference count. Are you using ref() and unref() + // directly? Are you sure you can't use PointerTo's? + nassertr(_node_ref_count > 0, false); + + unref(); + return AtomicAdjust::dec(((NodeCachedReferenceCount *)this)->_node_ref_count); +} + + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::test_ref_count_integrity +// Access: Published +// Description: Does some easy checks to make sure that the reference +// count isn't completely bogus. +//////////////////////////////////////////////////////////////////// +INLINE void NodeCachedReferenceCount:: +test_ref_count_integrity() const { +#ifndef NDEBUG + nassertv(this != NULL); + + // If this assertion fails, we're trying to delete an object that + // was just deleted. Possibly you used a real pointer instead of a + // PointerTo at some point, and the object was deleted when the + // PointerTo went out of scope. Maybe you tried to create an + // automatic (local variable) instance of a class that derives from + // ReferenceCount. Or maybe your headers are out of sync, and you + // need to make clean in direct or some higher tree. + nassertv(_node_ref_count != -100); + + // If this assertion fails, the reference counts are all screwed + // up altogether. Maybe some errant code stomped all over memory + // somewhere. + nassertv(_node_ref_count >= 0); + + CachedTypedWritableReferenceCount::test_ref_count_integrity(); +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeCachedReferenceCount::get_referenced_bits +// Access: Published +// Description: Returns the union of the values defined in the +// Referenced enum that represents the various things +// that appear to be holding a pointer to this object. +// +// If R_node is included, at least one node is holding a +// pointer; if R_cache is included, at least one cache +// element is. +//////////////////////////////////////////////////////////////////// +INLINE int NodeCachedReferenceCount:: +get_referenced_bits() const { + int result = 0; + if (get_node_ref_count() != 0) { + result |= R_node; + } + if (get_cache_ref_count() != 0) { + result |= R_cache; + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: node_unref_delete +// Description: This global helper function will unref the given +// ReferenceCount object, and if the reference count +// reaches zero, automatically delete it. It can't be a +// member function because it's usually a bad idea to +// delete an object from within its own member function. +// It's a template function so the destructor doesn't +// have to be virtual. +//////////////////////////////////////////////////////////////////// +template +INLINE void +node_unref_delete(RefCountType *ptr) { + ptr->node_unref(); + if (ptr->get_ref_count() == 0) { +#ifndef NDEBUG + if (get_leak_memory()) { + // In leak-memory mode, we don't actually delete the pointer, + // although we do call the destructor explicitly. This has + // exactly the same effect as deleting it, without actually + // freeing up the memory it uses. + + // Furthermore, if we have never-destruct set, we don't even + // call the destructor. + if (!get_never_destruct()) { + ptr->~RefCountType(); + } + return; + } +#endif + delete ptr; + } +} + diff --git a/panda/src/putil/nodeCachedReferenceCount.cxx b/panda/src/putil/nodeCachedReferenceCount.cxx new file mode 100644 index 0000000000..b8f3f4be45 --- /dev/null +++ b/panda/src/putil/nodeCachedReferenceCount.cxx @@ -0,0 +1,22 @@ +// Filename: nodeCachedReferenceCount.cxx +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "nodeCachedReferenceCount.h" + +TypeHandle NodeCachedReferenceCount::_type_handle; + diff --git a/panda/src/putil/nodeCachedReferenceCount.h b/panda/src/putil/nodeCachedReferenceCount.h new file mode 100644 index 0000000000..76aeeb1473 --- /dev/null +++ b/panda/src/putil/nodeCachedReferenceCount.h @@ -0,0 +1,95 @@ +// Filename: nodeCachedReferenceCount.h +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef NODECACHEDREFERENCECOUNT_H +#define NODECACHEDREFERENCECOUNT_H + +#include "pandabase.h" + +#include "cachedTypedWritableReferenceCount.h" + +//////////////////////////////////////////////////////////////////// +// Class : NodeCachedReferenceCount +// Description : This class further specializes +// CachedTypedWritableReferenceCount to also add a +// node_ref_count, for the purposes of counting the +// number of times the object is referenced by a "node", +// presumably a PandaNode. +// +// The intended design is to use this as a base class +// for RenderState and TransformState, both of which are +// held by PandaNodes, and also have caches which are +// independently maintained. By keeping track of how +// many nodes hold a pointer to a particular object, we +// can classify each object into node-referenced, +// cache-referenced, or other, which is primarily useful +// for PStats reporting. +// +// As with CachedTypedWritableReferenceCount's +// cache_ref() and cache_unref(), the new methods +// node_ref() and node_unref() automatically increment +// and decrement the primary reference count as well. +// In this case, however, there does exist a +// NodePointerTo<> class to maintain the node_ref +// counters automatically. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA NodeCachedReferenceCount : public CachedTypedWritableReferenceCount { +protected: + INLINE NodeCachedReferenceCount(); + INLINE NodeCachedReferenceCount(const NodeCachedReferenceCount ©); + INLINE void operator = (const NodeCachedReferenceCount ©); + INLINE ~NodeCachedReferenceCount(); + +PUBLISHED: + INLINE int get_node_ref_count() const; + INLINE int node_ref() const; + INLINE int node_unref() const; + INLINE void test_ref_count_integrity() const; + + enum Referenced { + R_node = 0x001, + R_cache = 0x002, + }; + + INLINE int get_referenced_bits() const; + +private: + int _node_ref_count; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + + static void init_type() { + CachedTypedWritableReferenceCount::init_type(); + register_type(_type_handle, "NodeCachedReferenceCount", + CachedTypedWritableReferenceCount::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +template +INLINE void node_unref_delete(RefCountType *ptr); + +#include "nodeCachedReferenceCount.I" + +#endif + diff --git a/panda/src/putil/nodePointerTo.I b/panda/src/putil/nodePointerTo.I new file mode 100644 index 0000000000..b8c1d360ed --- /dev/null +++ b/panda/src/putil/nodePointerTo.I @@ -0,0 +1,239 @@ +// Filename: nodePointerTo.I +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo:: +NodePointerTo(To *ptr) : NodePointerToBase(ptr) { +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo:: +NodePointerTo(const NodePointerTo ©) : + NodePointerToBase((const NodePointerToBase &)copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Dereference operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE TYPENAME NodePointerTo::To &NodePointerTo:: +operator *() const { + return *((To *)(this->_void_ptr)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Member access operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE TYPENAME NodePointerTo::To *NodePointerTo:: +operator -> () const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Typecast operator +// Access: Public +// Description: We also have the typecast operator to automatically +// convert NodePointerTo's to the required kind of actual +// pointer. This introduces ambiguities which the +// compiler will resolve one way or the other, but we +// don't care which way it goes because either will be +// correct. +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo:: +operator TYPENAME NodePointerToBase::To *() const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::p +// Access: Public +// Description: Returns an ordinary pointer instead of a NodePointerTo. +// Useful to work around compiler problems, particularly +// for implicit upcasts. +//////////////////////////////////////////////////////////////////// +template +INLINE TYPENAME NodePointerTo::To *NodePointerTo:: +p() const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo &NodePointerTo:: +operator = (To *ptr) { + reassign(ptr); + return *this; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerTo::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerTo &NodePointerTo:: +operator = (const NodePointerTo ©) { + reassign((const NodePointerToBase &)copy); + return *this; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo:: +NodeConstPointerTo(const TYPENAME NodeConstPointerTo::To *ptr) : + NodePointerToBase((TYPENAME NodeConstPointerTo::To *)ptr) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo:: +NodeConstPointerTo(const NodePointerTo ©) : + NodePointerToBase((const NodePointerToBase &)copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo:: +NodeConstPointerTo(const NodeConstPointerTo ©) : + NodePointerToBase((const NodePointerToBase &)copy) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Dereference operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE const TYPENAME NodeConstPointerTo::To &NodeConstPointerTo:: +operator *() const { + return *((To *)(this->_void_ptr)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Member access operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE const TYPENAME NodeConstPointerTo::To *NodeConstPointerTo:: +operator -> () const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Typecast operator +// Access: Public +// Description: We also have the typecast operator to automatically +// convert NodeConstPointerTo's to the required kind of actual +// pointer. This introduces ambiguities which the +// compiler will resolve one way or the other, but we +// don't care which way it goes because either will be +// correct. +//////////////////////////////////////////////////////////////////// + +template +INLINE NodeConstPointerTo:: +operator const TYPENAME NodePointerToBase::To *() const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::p +// Access: Public +// Description: Returns an ordinary pointer instead of a NodeConstPointerTo. +// Useful to work around compiler problems, particularly +// for implicit upcasts. +//////////////////////////////////////////////////////////////////// +template +INLINE const TYPENAME NodeConstPointerTo::To *NodeConstPointerTo:: +p() const { + return (To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo &NodeConstPointerTo:: +operator = (const To *ptr) { + reassign((To *)ptr); + return *this; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo &NodeConstPointerTo:: +operator = (const NodePointerTo ©) { + reassign((const NodePointerToBase &)copy); + return *this; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeConstPointerTo::Assignment operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodeConstPointerTo &NodeConstPointerTo:: +operator = (const NodeConstPointerTo ©) { + reassign((const NodePointerToBase &)copy); + return *this; +} diff --git a/panda/src/putil/nodePointerTo.cxx b/panda/src/putil/nodePointerTo.cxx new file mode 100644 index 0000000000..541a45cb96 --- /dev/null +++ b/panda/src/putil/nodePointerTo.cxx @@ -0,0 +1,19 @@ +// Filename: nodePointerTo.cxx +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "nodePointerTo.h" diff --git a/panda/src/putil/nodePointerTo.h b/panda/src/putil/nodePointerTo.h new file mode 100644 index 0000000000..1a09856a5e --- /dev/null +++ b/panda/src/putil/nodePointerTo.h @@ -0,0 +1,81 @@ +// Filename: nodePointerTo.h +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef NODEPOINTERTO_H +#define NODEPOINTERTO_H + +#include "pandabase.h" +#include "nodePointerToBase.h" + +//////////////////////////////////////////////////////////////////// +// Class : NodePointerTo +// Description : + +// This implements the special NodePointerTo template +// class, which works just like PointerTo except it +// manages the objects node_ref_count instead of the +// normal ref_count. +//////////////////////////////////////////////////////////////////// +template +class NodePointerTo : public NodePointerToBase { +public: + typedef TYPENAME NodePointerToBase::To To; + INLINE NodePointerTo(To *ptr = (To *)NULL); + INLINE NodePointerTo(const NodePointerTo ©); + + INLINE To &operator *() const; + INLINE To *operator -> () const; + INLINE operator TYPENAME NodePointerToBase::To *() const; + + INLINE To *p() const; + + INLINE NodePointerTo &operator = (To *ptr); + INLINE NodePointerTo &operator = (const NodePointerTo ©); +}; + + +//////////////////////////////////////////////////////////////////// +// Class : NodeConstPointerTo +// Description : A NodeConstPointerTo is similar to a NodePointerTo, +// except it keeps a const pointer to the thing. +//////////////////////////////////////////////////////////////////// +template +class NodeConstPointerTo : public NodePointerToBase { +public: + typedef TYPENAME NodePointerToBase::To To; + INLINE NodeConstPointerTo(const To *ptr = (const To *)NULL); + INLINE NodeConstPointerTo(const NodePointerTo ©); + INLINE NodeConstPointerTo(const NodeConstPointerTo ©); + + INLINE const To &operator *() const; + INLINE const To *operator -> () const; + INLINE operator const TYPENAME NodePointerToBase::To *() const; + + INLINE const To *p() const; + + INLINE NodeConstPointerTo &operator = (const To *ptr); + INLINE NodeConstPointerTo &operator = (const NodePointerTo ©); + INLINE NodeConstPointerTo &operator = (const NodeConstPointerTo ©); +}; + +#define NPT(type) NodePointerTo< type > +#define NCPT(type) NodeConstPointerTo< type > + +#include "nodePointerTo.I" + +#endif diff --git a/panda/src/putil/nodePointerToBase.I b/panda/src/putil/nodePointerToBase.I new file mode 100644 index 0000000000..8c7dd89147 --- /dev/null +++ b/panda/src/putil/nodePointerToBase.I @@ -0,0 +1,135 @@ +// Filename: nodePointerToBase.I +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerToBase:: +NodePointerToBase(To *ptr) { + reassign(ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerToBase:: +NodePointerToBase(const NodePointerToBase ©) { + reassign(copy); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::Destructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE NodePointerToBase:: +~NodePointerToBase() { + reassign((To *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::reassign +// Access: Protected +// Description: This is the main work of the NodePointerTo family. When +// the pointer is reassigned, decrement the old +// reference count and increment the new one. +//////////////////////////////////////////////////////////////////// +template +void NodePointerToBase:: +reassign(To *ptr) { + if (ptr != (To *)_void_ptr) { + // First save the old pointer; we won't delete it until we have + // assigned the new one. We do this just in case there are + // cascading effects from deleting this pointer that might + // inadvertently delete the new one. (Don't laugh--it's + // happened!) + To *old_ptr = (To *)_void_ptr; + + _void_ptr = (void *)ptr; + if (ptr != (To *)NULL) { + ptr->node_ref(); +#ifdef DO_MEMORY_USAGE + if (MemoryUsage::get_track_memory_usage()) { + // Make sure the MemoryUsage record knows what the TypeHandle + // is, if we know it ourselves. + TypeHandle type = get_type_handle(To); + if (type == TypeHandle::none()) { + do_init_type(To); + type = get_type_handle(To); + } + if (type != TypeHandle::none()) { + MemoryUsage::update_type(ptr, type); + } + } +#endif + } + + // Now delete the old pointer. + if (old_ptr != (To *)NULL) { + node_unref_delete(old_ptr); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::reassign +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +template +INLINE void NodePointerToBase:: +reassign(const NodePointerToBase ©) { + reassign((To *)copy._void_ptr); +} + + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::clear +// Access: Published +// Description: A convenient way to set the NodePointerTo object to NULL. +// (Assignment to a NULL pointer also works, of course.) +//////////////////////////////////////////////////////////////////// +template +INLINE void NodePointerToBase:: +clear() { + reassign((To *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePointerToBase::output +// Access: Published +// Description: A handy function to output NodePointerTo's as a hex +// pointer followed by a reference count. +//////////////////////////////////////////////////////////////////// +template +INLINE void NodePointerToBase:: +output(ostream &out) const { + out << _void_ptr; + if (_void_ptr != (void *)NULL) { + out << ":" << ((To *)_void_ptr)->get_node_ref_count() << "/" + << ((To *)_void_ptr)->get_ref_count(); + } +} diff --git a/panda/src/putil/nodePointerToBase.cxx b/panda/src/putil/nodePointerToBase.cxx new file mode 100644 index 0000000000..ea382868eb --- /dev/null +++ b/panda/src/putil/nodePointerToBase.cxx @@ -0,0 +1,19 @@ +// Filename: nodePointerToBase.cxx +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "nodePointerToBase.h" diff --git a/panda/src/putil/nodePointerToBase.h b/panda/src/putil/nodePointerToBase.h new file mode 100644 index 0000000000..5212647912 --- /dev/null +++ b/panda/src/putil/nodePointerToBase.h @@ -0,0 +1,70 @@ +// Filename: nodePointerToBase.h +// Created by: drose (07May05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef NODEPOINTERTOBASE_H +#define NODEPOINTERTOBASE_H + +#include "pandabase.h" +#include "pointerToVoid.h" +#include "nodeCachedReferenceCount.h" +#include "memoryUsage.h" +#include "config_express.h" + +//////////////////////////////////////////////////////////////////// +// Class : NodePointerToBase +// Description : This is similar to PointerToBase, but it manages +// objects of type NodeCachedReferenceCount, and it +// updates the node_ref_count instead of the regular +// ref_count. It is intended for use only in PandaNode, +// to hold a pointer to RenderState and TransformState, +// although it could be used by any object that wanted +// to maintain a separate reference count for reporting +// purposes. +//////////////////////////////////////////////////////////////////// +template +class NodePointerToBase : public PointerToVoid { +public: + typedef T To; + +protected: + INLINE NodePointerToBase(To *ptr); + INLINE NodePointerToBase(const NodePointerToBase ©); + INLINE ~NodePointerToBase(); + + void reassign(To *ptr); + INLINE void reassign(const NodePointerToBase ©); + + // No assignment or retrieval functions are declared in + // NodePointerToBase, because we will have to specialize on const + // vs. non-const later. + +PUBLISHED: + INLINE void clear(); + + void output(ostream &out) const; +}; + +template +INLINE ostream &operator <<(ostream &out, const NodePointerToBase &pointer) { + pointer.output(out); + return out; +} + +#include "nodePointerToBase.I" + +#endif diff --git a/panda/src/putil/putil_composite1.cxx b/panda/src/putil/putil_composite1.cxx index a0d2c1563c..5fe0560119 100644 --- a/panda/src/putil/putil_composite1.cxx +++ b/panda/src/putil/putil_composite1.cxx @@ -24,6 +24,3 @@ #include "lineStreamBuf.cxx" #include "load_prc_file.cxx" #include "modifierButtons.cxx" -#include "mouseButton.cxx" -#include "mouseData.cxx" - diff --git a/panda/src/putil/putil_composite2.cxx b/panda/src/putil/putil_composite2.cxx index 6a8b3c6c38..853aa4eefa 100644 --- a/panda/src/putil/putil_composite2.cxx +++ b/panda/src/putil/putil_composite2.cxx @@ -1,4 +1,9 @@ +#include "mouseButton.cxx" +#include "mouseData.cxx" #include "nameUniquifier.cxx" +#include "nodeCachedReferenceCount.cxx" +#include "nodePointerToBase.cxx" +#include "nodePointerTo.cxx" #include "pipeline.cxx" #include "pipelineCycler.cxx" #include "pipelineCyclerBase.cxx"