implement cache-check-timestamps for models

This commit is contained in:
David Rose 2012-02-26 03:02:57 +00:00
parent 7db604c791
commit ec81b415a5
2 changed files with 79 additions and 16 deletions

View File

@ -30,9 +30,15 @@ has_model(const Filename &filename) {
// Description: Loads the given filename up as a model, if it has
// not already been loaded, and returns true to indicate
// success, or false to indicate failure. If this
// returns true, it is guaranteed that a subsequent call
// returns true, it is probable that a subsequent call
// to load_model() with the same model name will
// return a valid Node pointer.
// return a valid PandaNode.
//
// However, even if this returns true, it is still
// possible for a subsequent call to load_model() to
// fail. This can happen if cache-check-timestamps is
// true, and the on-disk file is subsequently modified
// to replace it with an invalid model.
////////////////////////////////////////////////////////////////////
INLINE bool ModelPool::
verify_model(const Filename &filename) {
@ -45,8 +51,11 @@ verify_model(const Filename &filename) {
// Description: Loads the given filename up as a model, if it has
// not already been loaded, and returns the new model.
// If a model with the same filename was previously
// loaded, returns that one instead. If the model
// file cannot be found, returns NULL.
// loaded, returns that one instead (unless
// cache-check-timestamps is true and the file has
// recently changed). If the model file cannot be
// found, or cannot be loaded for some reason, returns
// NULL.
////////////////////////////////////////////////////////////////////
INLINE ModelRoot *ModelPool::
load_model(const Filename &filename, const LoaderOptions &options) {
@ -57,9 +66,8 @@ load_model(const Filename &filename, const LoaderOptions &options) {
// Function: ModelPool::add_model
// Access: Public, Static
// Description: Adds the indicated already-loaded model to the
// pool. The model will always replace any
// previously-loaded model in the pool that had the
// same filename.
// pool. The model will replace any previously-loaded
// model in the pool that had the same filename.
//
// This two-parameter version of this method is
// deprecated; use the one-parameter add_model(model)
@ -91,9 +99,8 @@ release_model(const Filename &filename) {
// Function: ModelPool::add_model
// Access: Public, Static
// Description: Adds the indicated already-loaded model to the
// pool. The model will always replace any
// previously-loaded model in the pool that had the
// same filename.
// pool. The model will replace any previously-loaded
// model in the pool that had the same filename.
////////////////////////////////////////////////////////////////////
INLINE void ModelPool::
add_model(ModelRoot *model) {
@ -105,9 +112,10 @@ add_model(ModelRoot *model) {
// Access: Public, Static
// Description: Removes the indicated model from the pool,
// indicating it will never be loaded again; the model
// may then be freed. If this function is never called,
// a reference count will be maintained on every model
// every loaded, and models will never be freed.
// may then be freed. If this function (and
// garbage_collect()) is never called, a reference count
// will be maintained on every model every loaded, and
// models will never be freed.
//
// The model's get_fullpath() value should not have been
// changed during its lifetime, or this function may

View File

@ -57,16 +57,67 @@ ns_has_model(const Filename &filename) {
////////////////////////////////////////////////////////////////////
ModelRoot *ModelPool::
ns_load_model(const Filename &filename, const LoaderOptions &options) {
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
PT(ModelRoot) cached_model;
bool got_cached_model = false;
{
LightMutexHolder holder(_lock);
Models::const_iterator ti;
ti = _models.find(filename);
if (ti != _models.end()) {
// This model was previously loaded.
return (*ti).second;
// This filename was previously loaded.
cached_model = (*ti).second;
got_cached_model = true;
}
}
if (got_cached_model) {
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
<< "ModelPool found " << cached_model << " for " << filename << "\n";
}
if (cached_model == NULL) {
// This filename was previously attempted, but it did not
// exist (or the model could not be loaded for some reason).
if (cache_check_timestamps) {
// Check to see if there is a file there now.
if (vfs->exists(filename)) {
// There is, so try to load it.
got_cached_model = false;
}
}
} else {
// This filename was previously attempted, and successfully
// loaded.
if (cache_check_timestamps && cached_model->get_timestamp() != 0 &&
!cached_model->get_fullpath().empty()) {
// Compare the timestamp to the file on-disk.
PT(VirtualFile) vfile = vfs->get_file(cached_model->get_fullpath());
if (vfile == NULL) {
// The file has disappeared! Look further along the model-path.
got_cached_model = false;
} else if (vfile->get_timestamp() > cached_model->get_timestamp()) {
// The file still exists, but it has a newer timestamp than
// the one we previously loaded. Force it to re-load.
got_cached_model = false;
}
}
}
}
if (got_cached_model) {
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
<< "ModelPool returning " << cached_model << " for " << filename << "\n";
}
return cached_model;
}
// Look on disk for the current file.
LoaderOptions new_options(options);
new_options.set_flags((new_options.get_flags() | LoaderOptions::LF_no_ram_cache) &
~(LoaderOptions::LF_search | LoaderOptions::LF_report_errors));
@ -97,11 +148,15 @@ ns_load_model(const Filename &filename, const LoaderOptions &options) {
// another thread.
Models::const_iterator ti;
ti = _models.find(filename);
if (ti != _models.end()) {
if (ti != _models.end() && (*ti).second != cached_model) {
// This model was previously loaded.
return (*ti).second;
}
if (pgraph_cat.is_debug()) {
pgraph_cat.debug()
<< "ModelPool storing " << node << " for " << filename << "\n";
}
_models[filename] = node;
}