From 763808f8e465ea8e3728afc854e65719d964eebb Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 23 Oct 2006 20:50:09 +0000 Subject: [PATCH] make ModelPool::garbage_collect() behave sensibly in the new loadModel() world --- panda/src/pgraph/modelPool.I | 6 ++-- panda/src/pgraph/modelPool.cxx | 27 +++++++++----- panda/src/pgraph/modelPool.h | 12 +++---- panda/src/pgraph/modelRoot.I | 64 +++++++++++++++++++++++++++++++--- panda/src/pgraph/modelRoot.h | 18 ++++++++-- 5 files changed, 103 insertions(+), 24 deletions(-) diff --git a/panda/src/pgraph/modelPool.I b/panda/src/pgraph/modelPool.I index 542c93d295..503f1eec87 100644 --- a/panda/src/pgraph/modelPool.I +++ b/panda/src/pgraph/modelPool.I @@ -40,7 +40,7 @@ has_model(const string &filename) { //////////////////////////////////////////////////////////////////// INLINE bool ModelPool:: verify_model(const string &filename) { - return load_model(filename) != (PandaNode *)NULL; + return load_model(filename) != (ModelRoot *)NULL; } //////////////////////////////////////////////////////////////////// @@ -52,7 +52,7 @@ verify_model(const string &filename) { // loaded, returns that one instead. If the model // file cannot be found, returns NULL. //////////////////////////////////////////////////////////////////// -INLINE PandaNode *ModelPool:: +INLINE ModelRoot *ModelPool:: load_model(const string &filename, const LoaderOptions &options) { return get_ptr()->ns_load_model(filename, options); } @@ -66,7 +66,7 @@ load_model(const string &filename, const LoaderOptions &options) { // same filename. //////////////////////////////////////////////////////////////////// INLINE void ModelPool:: -add_model(const string &filename, PandaNode *model) { +add_model(const string &filename, ModelRoot *model) { get_ptr()->ns_add_model(filename, model); } diff --git a/panda/src/pgraph/modelPool.cxx b/panda/src/pgraph/modelPool.cxx index 2858bed991..27589376b4 100644 --- a/panda/src/pgraph/modelPool.cxx +++ b/panda/src/pgraph/modelPool.cxx @@ -61,7 +61,7 @@ ns_has_model(const string &filename) { // Access: Private // Description: The nonstatic implementation of load_model(). //////////////////////////////////////////////////////////////////// -PandaNode *ModelPool:: +ModelRoot *ModelPool:: ns_load_model(const string &filename, const LoaderOptions &options) { { MutexHolder holder(_lock); @@ -78,11 +78,20 @@ ns_load_model(const string &filename, const LoaderOptions &options) { LoaderOptions new_options(options); new_options.set_flags(new_options.get_flags() | LoaderOptions::LF_no_ram_cache); - PT(PandaNode) node = model_loader.load_sync(filename, new_options); - - if (node.is_null()) { + PT(PandaNode) panda_node = model_loader.load_sync(filename, new_options); + if (panda_node.is_null()) { // This model was not found. - return (PandaNode *)NULL; + return (ModelRoot *)NULL; + } + + PT(ModelRoot) node; + if (panda_node->is_of_type(ModelRoot::get_class_type())) { + node = DCAST(ModelRoot, panda_node); + + } else { + // We have to construct a ModelRoot node to put it under. + node = new ModelRoot(filename); + node->add_child(panda_node); } { @@ -109,7 +118,7 @@ ns_load_model(const string &filename, const LoaderOptions &options) { // Description: The nonstatic implementation of add_model(). //////////////////////////////////////////////////////////////////// void ModelPool:: -ns_add_model(const string &filename, PandaNode *model) { +ns_add_model(const string &filename, ModelRoot *model) { MutexHolder holder(_lock); // We blow away whatever model was there previously, if any. _models[filename] = model; @@ -155,8 +164,8 @@ ns_garbage_collect() { Models::iterator ti; for (ti = _models.begin(); ti != _models.end(); ++ti) { - PandaNode *node = (*ti).second; - if (node->get_ref_count() == 1) { + ModelRoot *node = (*ti).second; + if (node->get_model_ref_count() == 1) { if (loader_cat.is_debug()) { loader_cat.debug() << "Releasing " << (*ti).first << "\n"; @@ -184,7 +193,7 @@ ns_list_contents(ostream &out) const { Models::const_iterator ti; for (ti = _models.begin(); ti != _models.end(); ++ti) { out << " " << (*ti).first - << " (count = " << (*ti).second->get_ref_count() << ")\n"; + << " (count = " << (*ti).second->get_model_ref_count() << ")\n"; } } diff --git a/panda/src/pgraph/modelPool.h b/panda/src/pgraph/modelPool.h index 9b176481b9..6fe4c2f34b 100644 --- a/panda/src/pgraph/modelPool.h +++ b/panda/src/pgraph/modelPool.h @@ -22,7 +22,7 @@ #include "pandabase.h" #include "filename.h" -#include "pandaNode.h" +#include "modelRoot.h" #include "pointerTo.h" #include "pmutex.h" #include "pmap.h" @@ -51,10 +51,10 @@ class EXPCL_PANDA ModelPool { PUBLISHED: INLINE static bool has_model(const string &filename); INLINE static bool verify_model(const string &filename); - INLINE static PandaNode *load_model(const string &filename, + INLINE static ModelRoot *load_model(const string &filename, const LoaderOptions &options = LoaderOptions()); - INLINE static void add_model(const string &filename, PandaNode *model); + INLINE static void add_model(const string &filename, ModelRoot *model); INLINE static void release_model(const string &filename); INLINE static void release_all_models(); @@ -67,9 +67,9 @@ private: INLINE ModelPool(); bool ns_has_model(const string &filename); - PandaNode *ns_load_model(const string &filename, + ModelRoot *ns_load_model(const string &filename, const LoaderOptions &options); - void ns_add_model(const string &filename, PandaNode *model); + void ns_add_model(const string &filename, ModelRoot *model); void ns_release_model(const string &filename); void ns_release_all_models(); int ns_garbage_collect(); @@ -80,7 +80,7 @@ private: static ModelPool *_global_ptr; Mutex _lock; - typedef pmap Models; + typedef pmap Models; Models _models; }; diff --git a/panda/src/pgraph/modelRoot.I b/panda/src/pgraph/modelRoot.I index 94745320f5..374e06b5af 100644 --- a/panda/src/pgraph/modelRoot.I +++ b/panda/src/pgraph/modelRoot.I @@ -16,24 +16,80 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: ModelRoot::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE ModelRoot:: ModelRoot(const string &name) : - ModelNode(name) + ModelNode(name), + _reference(new ModelRoot::ModelReference) { } +//////////////////////////////////////////////////////////////////// +// Function: ModelRoot::get_model_ref_count +// Access: Published +// Description: Returns the number of copies that exist of this +// particular ModelRoot node. Each time +// ModelRoot::copy_subgraph() or make_copy() is called +// (or some other copying mechanism, such as +// NodePath.copy_to(), is used), this count will +// increment by one in all copies; when one of the +// copies is destructed, this count will decrement. +//////////////////////////////////////////////////////////////////// +INLINE int ModelRoot:: +get_model_ref_count() const { + return _reference->get_ref_count(); +} + +//////////////////////////////////////////////////////////////////// +// Function: ModelRoot::get_reference +// Access: Published +// Description: Returns the pointer that represents the object shared +// between all copies of this ModelRoot. Since there's +// not much associated with this object other than a +// reference count, normally there's not much reason to +// get the pointer (though it may be compared +// pointerwise with other ModelRoot objects). +//////////////////////////////////////////////////////////////////// +INLINE ModelRoot::ModelReference *ModelRoot:: +get_reference() const { + return _reference; +} + +//////////////////////////////////////////////////////////////////// +// Function: ModelRoot::set_reference +// Access: Published +// Description: Changes the pointer that represents the object shared +// between all copies of this ModelRoot. This will +// disassociate this ModelRoot from all of its copies. +// Normally, there's no reason to do this. +//////////////////////////////////////////////////////////////////// +INLINE void ModelRoot:: +set_reference(ModelRoot::ModelReference *ref) { + _reference = ref; +} + //////////////////////////////////////////////////////////////////// // Function: ModelRoot::Copy Constructor -// Access: Public +// Access: Protected // Description: //////////////////////////////////////////////////////////////////// INLINE ModelRoot:: ModelRoot(const ModelRoot ©) : - ModelNode(copy) + ModelNode(copy), + _reference(copy._reference) { } + +//////////////////////////////////////////////////////////////////// +// Function: ModelRoot::ModelReference::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE ModelRoot::ModelReference:: +ModelReference() { +} diff --git a/panda/src/pgraph/modelRoot.h b/panda/src/pgraph/modelRoot.h index ccb3cce86c..c7159ce461 100644 --- a/panda/src/pgraph/modelRoot.h +++ b/panda/src/pgraph/modelRoot.h @@ -20,7 +20,7 @@ #define MODELROOT_H #include "pandabase.h" - +#include "referenceCount.h" #include "modelNode.h" //////////////////////////////////////////////////////////////////// @@ -34,7 +34,18 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA ModelRoot : public ModelNode { PUBLISHED: - INLINE ModelRoot(const string &name ); + INLINE ModelRoot(const string &name); + + INLINE int get_model_ref_count() const; + + // This class is used to unify references to the same model. + class ModelReference : public ReferenceCount { + PUBLISHED: + INLINE ModelReference(); + }; + + INLINE ModelReference *get_reference() const; + INLINE void set_reference(ModelReference *ref); protected: INLINE ModelRoot(const ModelRoot ©); @@ -42,6 +53,9 @@ protected: public: virtual PandaNode *make_copy() const; +private: + PT(ModelReference) _reference; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg);