Panda3D
 All Classes Functions Variables Enumerations
modelPool.cxx
00001 // Filename: modelPool.cxx
00002 // Created by:  drose (12Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "modelPool.h"
00016 #include "loader.h"
00017 #include "config_pgraph.h"
00018 #include "lightMutexHolder.h"
00019 
00020 
00021 ModelPool *ModelPool::_global_ptr = (ModelPool *)NULL;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: ModelPool::write
00025 //       Access: Published, Static
00026 //  Description: Lists the contents of the model pool to the
00027 //               indicated output stream.
00028 //               Helps with debugging.
00029 ////////////////////////////////////////////////////////////////////
00030 void ModelPool::
00031 write(ostream &out) {
00032   get_ptr()->ns_list_contents(out);
00033 }
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: ModelPool::ns_has_model
00037 //       Access: Private
00038 //  Description: The nonstatic implementation of has_model().
00039 ////////////////////////////////////////////////////////////////////
00040 bool ModelPool::
00041 ns_has_model(const Filename &filename) {
00042   LightMutexHolder holder(_lock);
00043   Models::const_iterator ti;
00044   ti = _models.find(filename);
00045   if (ti != _models.end() && (*ti).second != (ModelRoot *)NULL) {
00046     // This model was previously loaded.
00047     return true;
00048   }
00049 
00050   return false;
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: ModelPool::ns_load_model
00055 //       Access: Private
00056 //  Description: The nonstatic implementation of load_model().
00057 ////////////////////////////////////////////////////////////////////
00058 ModelRoot *ModelPool::
00059 ns_load_model(const Filename &filename, const LoaderOptions &options) {
00060   {
00061     LightMutexHolder holder(_lock);
00062     Models::const_iterator ti;
00063     ti = _models.find(filename);
00064     if (ti != _models.end()) {
00065       // This model was previously loaded.
00066       return (*ti).second;
00067     }
00068   }
00069 
00070   LoaderOptions new_options(options);
00071   new_options.set_flags((new_options.get_flags() | LoaderOptions::LF_no_ram_cache) &
00072                         ~(LoaderOptions::LF_search | LoaderOptions::LF_report_errors));
00073 
00074   Loader *model_loader = Loader::get_global_ptr();
00075   PT(PandaNode) panda_node = model_loader->load_sync(filename, new_options);
00076   PT(ModelRoot) node;
00077 
00078   if (panda_node.is_null()) {
00079     // This model was not found.
00080 
00081   } else {
00082     if (panda_node->is_of_type(ModelRoot::get_class_type())) {
00083       node = DCAST(ModelRoot, panda_node);
00084       
00085     } else {
00086       // We have to construct a ModelRoot node to put it under.
00087       node = new ModelRoot(filename);
00088       node->add_child(panda_node);
00089     }
00090     node->set_fullpath(filename);
00091   }
00092 
00093   {
00094     LightMutexHolder holder(_lock);
00095 
00096     // Look again, in case someone has just loaded the model in
00097     // another thread.
00098     Models::const_iterator ti;
00099     ti = _models.find(filename);
00100     if (ti != _models.end()) {
00101       // This model was previously loaded.
00102       return (*ti).second;
00103     }
00104 
00105     _models[filename] = node;
00106   }
00107 
00108   return node;
00109 }
00110 
00111 ////////////////////////////////////////////////////////////////////
00112 //     Function: ModelPool::ns_add_model
00113 //       Access: Private
00114 //  Description: The nonstatic implementation of add_model().
00115 ////////////////////////////////////////////////////////////////////
00116 void ModelPool::
00117 ns_add_model(const Filename &filename, ModelRoot *model) {
00118   LightMutexHolder holder(_lock);
00119   // We blow away whatever model was there previously, if any.
00120   _models[filename] = model;
00121 }
00122 
00123 ////////////////////////////////////////////////////////////////////
00124 //     Function: ModelPool::ns_release_model
00125 //       Access: Private
00126 //  Description: The nonstatic implementation of release_model().
00127 ////////////////////////////////////////////////////////////////////
00128 void ModelPool::
00129 ns_release_model(const Filename &filename) {
00130   LightMutexHolder holder(_lock);
00131   Models::iterator ti;
00132   ti = _models.find(filename);
00133   if (ti != _models.end()) {
00134     _models.erase(ti);
00135   }
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: ModelPool::ns_add_model
00140 //       Access: Private
00141 //  Description: The nonstatic implementation of add_model().
00142 ////////////////////////////////////////////////////////////////////
00143 void ModelPool::
00144 ns_add_model(ModelRoot *model) {
00145   LightMutexHolder holder(_lock);
00146   // We blow away whatever model was there previously, if any.
00147   _models[model->get_fullpath()] = model;
00148 }
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: ModelPool::ns_release_model
00152 //       Access: Private
00153 //  Description: The nonstatic implementation of release_model().
00154 ////////////////////////////////////////////////////////////////////
00155 void ModelPool::
00156 ns_release_model(ModelRoot *model) {
00157   LightMutexHolder holder(_lock);
00158   Models::iterator ti;
00159   ti = _models.find(model->get_fullpath());
00160   if (ti != _models.end()) {
00161     _models.erase(ti);
00162   }
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: ModelPool::ns_release_all_models
00167 //       Access: Private
00168 //  Description: The nonstatic implementation of release_all_models().
00169 ////////////////////////////////////////////////////////////////////
00170 void ModelPool::
00171 ns_release_all_models() {
00172   LightMutexHolder holder(_lock);
00173   _models.clear();
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: ModelPool::ns_garbage_collect
00178 //       Access: Private
00179 //  Description: The nonstatic implementation of garbage_collect().
00180 ////////////////////////////////////////////////////////////////////
00181 int ModelPool::
00182 ns_garbage_collect() {
00183   LightMutexHolder holder(_lock);
00184 
00185   int num_released = 0;
00186   Models new_set;
00187 
00188   Models::iterator ti;
00189   for (ti = _models.begin(); ti != _models.end(); ++ti) {
00190     ModelRoot *node = (*ti).second;
00191     if (node == (ModelRoot *)NULL ||
00192         node->get_model_ref_count() == 1) {
00193       if (loader_cat.is_debug()) {
00194         loader_cat.debug()
00195           << "Releasing " << (*ti).first << "\n";
00196       }
00197       ++num_released;
00198     } else {
00199       new_set.insert(new_set.end(), *ti);
00200     }
00201   }
00202 
00203   _models.swap(new_set);
00204   return num_released;
00205 }
00206 
00207 ////////////////////////////////////////////////////////////////////
00208 //     Function: ModelPool::ns_list_contents
00209 //       Access: Private
00210 //  Description: The nonstatic implementation of list_contents().
00211 ////////////////////////////////////////////////////////////////////
00212 void ModelPool::
00213 ns_list_contents(ostream &out) const {
00214   LightMutexHolder holder(_lock);
00215 
00216   out << "model pool contents:\n";
00217   
00218   Models::const_iterator ti;
00219   int num_models = 0;
00220   for (ti = _models.begin(); ti != _models.end(); ++ti) {
00221     if ((*ti).second != NULL) {
00222       ++num_models;
00223       out << (*ti).first << "\n"
00224           << "  (count = " << (*ti).second->get_model_ref_count() 
00225           << ")\n";
00226     }
00227   }
00228   
00229   out << "total number of models: " << num_models << " (plus " 
00230       << _models.size() - num_models << " entries for nonexistent files)\n";
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: ModelPool::get_ptr
00235 //       Access: Private, Static
00236 //  Description: Initializes and/or returns the global pointer to the
00237 //               one ModelPool object in the system.
00238 ////////////////////////////////////////////////////////////////////
00239 ModelPool *ModelPool::
00240 get_ptr() {
00241   if (_global_ptr == (ModelPool *)NULL) {
00242     _global_ptr = new ModelPool;
00243   }
00244   return _global_ptr;
00245 }
 All Classes Functions Variables Enumerations