[Scummvm-git-logs] scummvm master -> 606a7a3e792028ec34cfe13617053b739f6dc62a
sev-
noreply at scummvm.org
Sun Dec 11 20:34:02 UTC 2022
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
606a7a3e79 COMMON: Make MemcachingCaseInsensitiveArchive configurably to use weak pointers
Commit: 606a7a3e792028ec34cfe13617053b739f6dc62a
https://github.com/scummvm/scummvm/commit/606a7a3e792028ec34cfe13617053b739f6dc62a
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-12-11T21:33:59+01:00
Commit Message:
COMMON: Make MemcachingCaseInsensitiveArchive configurably to use weak pointers
This allows to keep memory footprint low on systems that are low on memory
Changed paths:
common/archive.cpp
common/archive.h
diff --git a/common/archive.cpp b/common/archive.cpp
index a61aa2fc331..cb76330791f 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -63,16 +63,42 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const Path &pattern) c
SeekableReadStream *MemcachingCaseInsensitiveArchive::createReadStreamForMember(const Path &path) const {
String translated = translatePath(path);
+ bool isNew = false;
if (!_cache.contains(translated)) {
_cache[translated] = readContentsForPath(translated);
+ isNew = true;
}
- const SharedArchiveContents& entry = _cache[translated];
+ SharedArchiveContents* entry = &_cache[translated];
- if (entry.isFileMissing())
+ // Errors and missing files. Just return nullptr,
+ // no need to create stream.
+ if (entry->isFileMissing())
return nullptr;
- return new Common::MemoryReadStream(entry.getContents(), entry.getSize());
+ // Check whether the entry is still valid as WeakPtr might have expired.
+ if (!entry->makeStrong()) {
+ // If it's expired, recreate the entry.
+ _cache[translated] = readContentsForPath(translated);
+ entry = &_cache[translated];
+ isNew = true;
+ }
+
+ // It's possible that recreation failed in case of e.g. network
+ // share going offline.
+ if (entry->isFileMissing())
+ return nullptr;
+
+ // Now we have a valid contents reference. Make stream for it.
+ Common::MemoryReadStream *memStream = new Common::MemoryReadStream(entry->getContents(), entry->getSize());
+
+ // If the entry was just created and it's too big for strong caching,
+ // mark the copy in cache as weak
+ if (isNew && entry->getSize() > _maxStronglyCachedSize) {
+ entry->makeWeak();
+ }
+
+ return memStream;
}
diff --git a/common/archive.h b/common/archive.h
index 2e89a8e992f..b2a8546e623 100644
--- a/common/archive.h
+++ b/common/archive.h
@@ -141,19 +141,48 @@ public:
virtual SeekableReadStream *createReadStreamForMember(const Path &path) const = 0;
};
+class MemcachingCaseInsensitiveArchive;
+
+// This is a shareable reference to a file contents stored in memory.
+// It can be in 2 states: strong when it holds a strong reference in
+// the sense of SharedPtr. Another state is weak when it only helds
+// WeakPtr and thus may expire. Also strong reference is held by
+// Returned memory stream. Hence once no memory streams and no
+// strong referenceas are remaining, the block is freed.
class SharedArchiveContents {
public:
- SharedArchiveContents(byte *contents, uint32 contentSize) : _contents(contents, ArrayDeleter<byte>()), _contentSize(contentSize), _missingFile(false) {}
- SharedArchiveContents() : _contents(nullptr), _contentSize(0), _missingFile(true) {}
+ SharedArchiveContents(byte *contents, uint32 contentSize) :
+ _strongRef(contents, ArrayDeleter<byte>()), _weakRef(_strongRef),
+ _contentSize(contentSize), _missingFile(false) {}
+ SharedArchiveContents() : _strongRef(nullptr), _weakRef(nullptr), _contentSize(0), _missingFile(true) {}
+private:
bool isFileMissing() const { return _missingFile; }
- SharedPtr<byte> getContents() const { return _contents; }
+ SharedPtr<byte> getContents() const { return _strongRef; }
uint32 getSize() const { return _contentSize; }
-private:
- SharedPtr<byte> _contents;
+ bool makeStrong() {
+ if (_strongRef || _contentSize == 0 || _missingFile)
+ return true;
+ _strongRef = SharedPtr<byte>(_weakRef);
+ if (_strongRef)
+ return true;
+ return false;
+ }
+
+ void makeWeak() {
+ // No need to make weak if we have no contents
+ if (_contentSize == 0)
+ return;
+ _strongRef = nullptr;
+ }
+
+ SharedPtr<byte> _strongRef;
+ WeakPtr<byte> _weakRef;
uint32 _contentSize;
bool _missingFile;
+
+ friend class MemcachingCaseInsensitiveArchive;
};
/**
@@ -161,6 +190,7 @@ private:
*/
class MemcachingCaseInsensitiveArchive : public Archive {
public:
+ MemcachingCaseInsensitiveArchive(uint32 maxStronglyCachedSize = 512) : _maxStronglyCachedSize(maxStronglyCachedSize) {}
SeekableReadStream *createReadStreamForMember(const Path &path) const;
virtual String translatePath(const Path &path) const {
@@ -173,6 +203,7 @@ public:
private:
mutable HashMap<String, SharedArchiveContents, IgnoreCase_Hash, IgnoreCase_EqualTo> _cache;
+ uint32 _maxStronglyCachedSize;
};
/**
More information about the Scummvm-git-logs
mailing list