Ticket #8912: kyra_resource_parent_cache_v3.diff
File kyra_resource_parent_cache_v3.diff, 5.8 KB (added by , 17 years ago) |
---|
-
resource.h
43 43 44 44 struct ResFileEntry { 45 45 Common::String parent; 46 mutable ResFileEntry *parentEntry; // Cache to avoid lookup by string in the map 47 // No smart invalidation is needed because the map is cleared globally 48 // or expanded but no element is ever removed 46 49 uint32 size; 47 50 48 51 bool preload; … … 129 132 protected: 130 133 void checkFile(const Common::String &file); 131 134 bool isAccessable(const Common::String &file); 135 bool isAccessable(const ResFileEntry *fileEntry); 132 136 133 137 void detectFileTypes(); 134 138 … … 140 144 LoaderList _loaders; 141 145 ResFileMap _map; 142 146 147 ResFileEntry *getParentEntry(const ResFileEntry *entry) const; 148 ResFileEntry *getParentEntry(const Common::String &filename) const; 149 143 150 typedef Common::List<Common::SharedPtr<CompArchiveLoader> > CompLoaderList; 144 151 typedef CompLoaderList::iterator CompLoaderIterator; 145 152 typedef CompLoaderList::const_iterator CCompLoaderIterator; -
resource.cpp
34 34 35 35 namespace Kyra { 36 36 37 static int sParentCacheHit = 0; 38 static int sParentCacheMiss = 0; 39 37 40 Resource::Resource(KyraEngine_v1 *vm) : _loaders(), _map(), _vm(vm) { 38 41 initializeLoaders(); 39 42 } … … 381 384 Common::SeekableReadStream *parent = getFileStream(iter->_value.parent); 382 385 assert(parent); 383 386 384 ResFile Map::const_iterator parentIter = _map.find(iter->_value.parent);385 const ResArchiveLoader *loader = getLoader(parent Iter->_value.type);387 ResFileEntry* parentEntry = getParentEntry(&iter->_value); 388 const ResArchiveLoader *loader = getLoader(parentEntry->type); 386 389 assert(loader); 387 390 388 391 return loader->loadFileFromArchive(file, parent, iter->_value); … … 395 398 checkFile(file); 396 399 397 400 ResFileMap::const_iterator iter = _map.find(file); 398 while (iter != _map.end()) { 399 if (!iter->_value.parent.empty()) { 400 iter = _map.find(iter->_value.parent); 401 if (iter != _map.end()) { 402 // parent can never be a non archive file 403 if (iter->_value.type == ResFileEntry::kRaw) 404 return false; 405 // not mounted parent means not accessable 406 else if (!iter->_value.mounted) 407 return false; 408 } 409 } else { 410 return true; 401 if (iter == _map.end()) 402 return false; 403 404 return isAccessable(&iter->_value); 405 } 406 407 bool Resource::isAccessable(const ResFileEntry *fileEntry) { 408 assert(fileEntry); 409 410 const ResFileEntry* currentEntry = fileEntry; 411 while (not currentEntry->parent.empty()) { 412 if (currentEntry->parentEntry) { 413 ++sParentCacheHit; 414 currentEntry = currentEntry->parentEntry; 411 415 } 416 else { 417 ++sParentCacheMiss; 418 ResFileMap::iterator it = _map.find(currentEntry->parent); 419 if (it == _map.end()) 420 return false; 421 else 422 currentEntry->parentEntry = &it->_value; 423 } 424 // parent can never be a non archive file 425 if (currentEntry->type == ResFileEntry::kRaw) 426 return false; 427 // not mounted parent means not accessable 428 else if (!currentEntry->mounted) 429 return false; 412 430 } 413 return false; 431 432 return true; 414 433 } 415 434 435 ResFileEntry *Resource::getParentEntry(const ResFileEntry *entry) const { 436 assert(entry); 437 if (entry->parent.empty()) 438 return NULL; 439 else if (entry->parentEntry) { 440 ++sParentCacheHit; 441 //printf ("%d %d %d\n", sParentCacheHit, sParentCacheMiss, sParentCacheHit+sParentCacheMiss); 442 assert(_map.find(entry->parent) != _map.end()); 443 assert(entry->parentEntry == &_map.find(entry->parent)->_value); 444 return entry->parentEntry; 445 } 446 else { 447 ++sParentCacheMiss; 448 ResFileMap::iterator it = _map.find(entry->parent); 449 if (it == _map.end()) 450 return NULL; // If it happens often, the structure maybe deserves a flag to avoid rechecking the map 451 else { 452 entry->parentEntry = &it->_value; 453 return entry->parentEntry; 454 } 455 } 456 } 457 458 ResFileEntry *Resource::getParentEntry(const Common::String &filename) const { 459 ResFileMap::iterator it = _map.find(filename); 460 assert(it != _map.end()); 461 return getParentEntry(&it->_value); 462 } 463 416 464 void Resource::checkFile(const Common::String &file) { 417 465 if (_map.find(file) == _map.end()) { 418 466 CompFileMap::const_iterator iter; … … 420 468 if ((iter = _compFiles.find(file)) != _compFiles.end()) { 421 469 ResFileEntry entry; 422 470 entry.parent = ""; 471 entry.parentEntry = NULL; 423 472 entry.size = iter->_value.size; 424 473 entry.mounted = false; 425 474 entry.preload = false; … … 434 483 if (temp.open(file)) { 435 484 ResFileEntry entry; 436 485 entry.parent = ""; 486 entry.parentEntry = NULL; 437 487 entry.size = temp.size(); 438 488 entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; 439 489 entry.preload = false; … … 451 501 452 502 void Resource::detectFileTypes() { 453 503 for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) { 454 if (!isAccessable( i->_key))504 if (!isAccessable(&i->_value)) 455 505 continue; 456 506 457 507 if (i->_value.type == ResFileEntry::kAutoDetect) { … … 620 670 entry.size = endoffset - startoffset; 621 671 entry.offset = startoffset; 622 672 entry.parent = filename; 673 entry.parentEntry = NULL; 623 674 entry.type = ResFileEntry::kAutoDetect; 624 675 entry.mounted = false; 625 676 entry.prot = false; … … 738 789 for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) { 739 790 ResFileEntry entry; 740 791 entry.parent = filename; 792 entry.parentEntry = NULL; 741 793 entry.type = ResFileEntry::kAutoDetect; 742 794 entry.mounted = false; 743 795 entry.preload = false; … … 807 859 for (uint i = 0; i < entries; ++i) { 808 860 ResFileEntry entry; 809 861 entry.parent = filename; 862 entry.parentEntry = NULL; 810 863 entry.type = ResFileEntry::kAutoDetect; 811 864 entry.mounted = false; 812 865 entry.preload = false;