QmlDesigner: Modernize project storage watcher and file status cache

Change-Id: Ia46d87803a74ebec7b7cc078115dd0bbbd02ec4d
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2025-03-22 14:50:10 +01:00
parent 0a7cc8e06e
commit 6a11b1bc58
5 changed files with 105 additions and 182 deletions

View File

@@ -24,9 +24,7 @@ public:
void addSourceContextId(SourceContextId sourceContextId)
{
auto found = std::lower_bound(m_sourceContextIds.begin(),
m_sourceContextIds.end(),
sourceContextId);
auto found = std::ranges::lower_bound(m_sourceContextIds, sourceContextId);
if (found == m_sourceContextIds.end() || *found != sourceContextId)
m_sourceContextIds.insert(found, sourceContextId);

View File

@@ -25,24 +25,9 @@ public:
&& first.lastModified == second.lastModified;
}
friend bool operator!=(const FileStatus &first, const FileStatus &second)
friend auto operator<=>(const FileStatus &first, const FileStatus &second)
{
return !(first == second);
}
friend bool operator<(const FileStatus &first, const FileStatus &second)
{
return first.sourceId < second.sourceId;
}
friend bool operator<(SourceId first, const FileStatus &second)
{
return first < second.sourceId;
}
friend bool operator<(const FileStatus &first, SourceId second)
{
return first.sourceId < second;
return first.sourceId <=> second.sourceId;
}
bool isExisting() const { return sourceId && size >= 0 && lastModified >= 0; }

View File

@@ -24,12 +24,7 @@ long long FileStatusCache::fileSize(SourceId sourceId) const
void FileStatusCache::update(SourceId sourceId)
{
auto found = std::lower_bound(m_cacheEntries.begin(),
m_cacheEntries.end(),
sourceId,
[](const auto &first, const auto &second) {
return first < second;
});
auto found = std::ranges::lower_bound(m_cacheEntries, sourceId, {}, &FileStatus::sourceId);
if (found != m_cacheEntries.end() && found->sourceId == sourceId)
*found = m_fileSystem.fileStatus(sourceId);
@@ -37,13 +32,12 @@ void FileStatusCache::update(SourceId sourceId)
void FileStatusCache::update(SourceIds sourceIds)
{
std::set_intersection(m_cacheEntries.begin(),
m_cacheEntries.end(),
sourceIds.begin(),
sourceIds.end(),
Utils::make_iterator([&](auto &entry) {
entry = m_fileSystem.fileStatus(entry.sourceId);
}));
Utils::set_greedy_intersection(
m_cacheEntries,
sourceIds,
[&](auto &entry) { entry = m_fileSystem.fileStatus(entry.sourceId); },
{},
&FileStatus::sourceId);
}
SourceIds FileStatusCache::modified(SourceIds sourceIds) const
@@ -51,44 +45,43 @@ SourceIds FileStatusCache::modified(SourceIds sourceIds) const
SourceIds modifiedSourceIds;
modifiedSourceIds.reserve(sourceIds.size());
std::set_intersection(m_cacheEntries.begin(),
m_cacheEntries.end(),
sourceIds.begin(),
sourceIds.end(),
Utils::make_iterator([&](auto &entry) {
auto fileStatus = m_fileSystem.fileStatus(entry.sourceId);
if (fileStatus != entry) {
modifiedSourceIds.push_back(entry.sourceId);
entry = fileStatus;
}
}));
Utils::set_greedy_intersection(
m_cacheEntries,
sourceIds,
[&](auto &entry) {
auto fileStatus = m_fileSystem.fileStatus(entry.sourceId);
if (fileStatus != entry) {
modifiedSourceIds.push_back(entry.sourceId);
entry = fileStatus;
}
},
{},
&FileStatus::sourceId);
FileStatuses newEntries;
newEntries.reserve(sourceIds.size());
std::set_difference(sourceIds.begin(),
sourceIds.end(),
m_cacheEntries.begin(),
m_cacheEntries.end(),
Utils::make_iterator([&](SourceId newSourceId) {
newEntries.push_back(m_fileSystem.fileStatus(newSourceId));
modifiedSourceIds.push_back(newSourceId);
}));
Utils::set_greedy_difference(
sourceIds,
m_cacheEntries,
[&](SourceId newSourceId) {
newEntries.push_back(m_fileSystem.fileStatus(newSourceId));
modifiedSourceIds.push_back(newSourceId);
},
{},
{},
&FileStatus::sourceId);
if (newEntries.size()) {
FileStatuses mergedEntries;
mergedEntries.reserve(m_cacheEntries.size() + newEntries.size());
std::set_union(newEntries.begin(),
newEntries.end(),
m_cacheEntries.begin(),
m_cacheEntries.end(),
std::back_inserter(mergedEntries));
std::ranges::set_union(newEntries, m_cacheEntries, std::back_inserter(mergedEntries));
m_cacheEntries = std::move(mergedEntries);
}
std::sort(modifiedSourceIds.begin(), modifiedSourceIds.end());
std::ranges::sort(modifiedSourceIds);
return modifiedSourceIds;
}
@@ -100,12 +93,7 @@ FileStatusCache::size_type FileStatusCache::size() const
const FileStatus &FileStatusCache::find(SourceId sourceId) const
{
auto found = std::lower_bound(m_cacheEntries.begin(),
m_cacheEntries.end(),
sourceId,
[](const auto &first, const auto &second) {
return first < second;
});
auto found = std::ranges::lower_bound(m_cacheEntries, sourceId, {}, &FileStatus::sourceId);
if (found != m_cacheEntries.end() && found->sourceId == sourceId)
return *found;

View File

@@ -13,27 +13,12 @@
#include <sourcepathstorage/storagecache.h>
#include <utils/algorithm.h>
#include <utils/set_algorithm.h>
#include <QTimer>
namespace QmlDesigner {
template<class InputIt1, class InputIt2, class Callable>
void set_greedy_intersection_call(
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Callable callable)
{
while (first1 != last1 && first2 != last2) {
if (*first1 < *first2) {
++first1;
} else {
if (*first2 < *first1)
++first2;
else
callable(*first1++);
}
}
}
template<typename FileSystemWatcher, typename Timer, class SourcePathCache>
class ProjectStoragePathWatcher : public ProjectStoragePathWatcherInterface,
public ProjectStorageTriggerUpdateInterface
@@ -63,7 +48,7 @@ public:
addEntries(entires);
auto notContainsdId = [&, &ids = ids](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
return !std::ranges::binary_search(ids, entry.id);
};
removeUnusedEntries(entires, notContainsdId);
}
@@ -76,10 +61,8 @@ public:
addEntries(entires);
auto notContainsId = [&, &ids = ids](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id)
|| !std::binary_search(sourceContextIds.begin(),
sourceContextIds.end(),
entry.sourceContextId);
return !std::ranges::binary_search(ids, entry.id)
|| !std::ranges::binary_search(sourceContextIds, entry.sourceContextId);
};
removeUnusedEntries(entires, notContainsId);
@@ -126,28 +109,22 @@ public:
ProjectChunkIds ids;
ids.reserve(ids.size());
auto outputIterator = std::back_inserter(entries);
for (const IdPaths &idPath : idPaths)
{
ProjectChunkId id = idPath.id;
ids.push_back(id);
outputIterator = std::transform(idPath.sourceIds.begin(),
idPath.sourceIds.end(),
outputIterator,
[&](SourceId sourceId) {
return WatcherEntry{id,
sourceId.contextId(),
sourceId,
m_fileStatusCache.lastModifiedTime(
sourceId)};
});
std::ranges::transform(idPath.sourceIds, std::back_inserter(entries), [&](SourceId sourceId) {
return WatcherEntry{id,
sourceId.contextId(),
sourceId,
m_fileStatusCache.lastModifiedTime(sourceId)};
});
}
std::sort(entries.begin(), entries.end());
std::sort(ids.begin(), ids.end());
std::ranges::sort(entries);
std::ranges::sort(ids);
return {entries, ids};
}
@@ -191,9 +168,9 @@ public:
SourceContextIds sourceContextIds = Utils::transform<SourceContextIds>(
watcherEntries, &WatcherEntry::sourceContextId);
std::sort(sourceContextIds.begin(), sourceContextIds.end());
sourceContextIds.erase(std::unique(sourceContextIds.begin(), sourceContextIds.end()),
sourceContextIds.end());
std::ranges::sort(sourceContextIds);
auto removed = std::ranges::unique(sourceContextIds);
sourceContextIds.erase(removed.begin(), removed.end());
return convertWatcherEntriesToDirectoryPathList(sourceContextIds);
}
@@ -203,11 +180,7 @@ public:
WatcherEntries notWatchedEntries;
notWatchedEntries.reserve(entries.size());
std::set_difference(entries.begin(),
entries.end(),
m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
std::back_inserter(notWatchedEntries));
std::ranges::set_difference(entries, m_watchedEntries, std::back_inserter(notWatchedEntries));
return notWatchedEntries;
}
@@ -217,11 +190,7 @@ public:
SourceContextIds notWatchedDirectoryIds;
notWatchedDirectoryIds.reserve(ids.size());
std::set_difference(ids.begin(),
ids.end(),
m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
std::back_inserter(notWatchedDirectoryIds));
std::ranges::set_difference(ids, m_watchedEntries, std::back_inserter(notWatchedDirectoryIds));
return notWatchedDirectoryIds;
}
@@ -232,12 +201,10 @@ public:
WatcherEntries notAnymoreWatchedEntries;
notAnymoreWatchedEntries.reserve(m_watchedEntries.size());
std::set_difference(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
newEntries.begin(),
newEntries.end(),
std::back_inserter(notAnymoreWatchedEntries),
compare);
std::ranges::set_difference(m_watchedEntries,
newEntries,
std::back_inserter(notAnymoreWatchedEntries),
compare);
return notAnymoreWatchedEntries;
}
@@ -245,11 +212,9 @@ public:
template<typename Filter>
WatcherEntries notAnymoreWatchedEntriesWithIds(const WatcherEntries &newEntries, Filter filter) const
{
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::less<WatcherEntry>());
auto oldEntries = notAnymoreWatchedEntries(newEntries, std::ranges::less{});
auto newEnd = std::remove_if(oldEntries.begin(), oldEntries.end(), filter);
oldEntries.erase(newEnd, oldEntries.end());
std::erase_if(oldEntries, filter);
return oldEntries;
}
@@ -259,11 +224,7 @@ public:
WatcherEntries newWatchedEntries;
newWatchedEntries.reserve(m_watchedEntries.size() + newEntries.size());
std::merge(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
newEntries.begin(),
newEntries.end(),
std::back_inserter(newWatchedEntries));
std::ranges::merge(m_watchedEntries, newEntries, std::back_inserter(newWatchedEntries));
m_watchedEntries = std::move(newWatchedEntries);
}
@@ -273,14 +234,10 @@ public:
SourceContextIds uniqueDirectoryIds;
uniqueDirectoryIds.reserve(pathEntries.size());
auto compare = [](WatcherEntry first, WatcherEntry second) {
return first.sourceContextId == second.sourceContextId;
};
std::unique_copy(pathEntries.begin(),
pathEntries.end(),
std::back_inserter(uniqueDirectoryIds),
compare);
std::ranges::unique_copy(pathEntries,
std::back_inserter(uniqueDirectoryIds),
{},
&WatcherEntry::sourceContextId);
return uniqueDirectoryIds;
}
@@ -294,15 +251,13 @@ public:
WatcherEntries removeIdsFromWatchedEntries(const ProjectPartIds &ids)
{
auto keep = [&](WatcherEntry entry) {
return !std::binary_search(ids.begin(), ids.end(), entry.id);
};
auto keep = [&](WatcherEntry entry) { return !std::ranges::binary_search(ids, entry.id.id); };
auto found = std::stable_partition(m_watchedEntries.begin(), m_watchedEntries.end(), keep);
auto removed = std::ranges::stable_partition(m_watchedEntries, keep);
WatcherEntries removedEntries(found, m_watchedEntries.end());
WatcherEntries removedEntries(removed.begin(), removed.end());
m_watchedEntries.erase(found, m_watchedEntries.end());
m_watchedEntries.erase(removed.begin(), removed.end());
return removedEntries;
}
@@ -312,11 +267,9 @@ public:
WatcherEntries newWatchedEntries;
newWatchedEntries.reserve(m_watchedEntries.size() - oldEntries.size());
std::set_difference(m_watchedEntries.cbegin(),
m_watchedEntries.cend(),
oldEntries.begin(),
oldEntries.end(),
std::back_inserter(newWatchedEntries));
std::ranges::set_difference(m_watchedEntries,
oldEntries,
std::back_inserter(newWatchedEntries));
m_watchedEntries = std::move(newWatchedEntries);
}
@@ -332,19 +285,19 @@ public:
WatcherEntries foundEntries;
foundEntries.reserve(m_watchedEntries.size());
set_greedy_intersection_call(m_watchedEntries.begin(),
m_watchedEntries.end(),
sourceContextIds.begin(),
sourceContextIds.end(),
[&](WatcherEntry &entry) {
m_fileStatusCache.update(entry.sourceId);
auto currentLastModified = m_fileStatusCache.lastModifiedTime(
entry.sourceId);
if (entry.lastModified < currentLastModified) {
foundEntries.push_back(entry);
entry.lastModified = currentLastModified;
}
});
Utils::set_greedy_intersection(
m_watchedEntries,
sourceContextIds,
[&](WatcherEntry &entry) {
m_fileStatusCache.update(entry.sourceId);
auto currentLastModified = m_fileStatusCache.lastModifiedTime(entry.sourceId);
if (entry.lastModified < currentLastModified) {
foundEntries.push_back(entry);
entry.lastModified = currentLastModified;
}
},
{},
&WatcherEntry::sourceContextId);
return foundEntries;
}
@@ -353,26 +306,31 @@ public:
{
auto sourceIds = Utils::transform<SourceIds>(entries, &WatcherEntry::sourceId);
std::sort(sourceIds.begin(), sourceIds.end());
sourceIds.erase(std::unique(sourceIds.begin(), sourceIds.end()), sourceIds.end());
std::ranges::sort(sourceIds);
auto removed = std::ranges::unique(sourceIds);
sourceIds.erase(removed.begin(), removed.end());
return sourceIds;
}
std::vector<IdPaths> idPathsForWatcherEntries(WatcherEntries &&foundEntries)
{
std::sort(foundEntries.begin(), foundEntries.end(), [](WatcherEntry first, WatcherEntry second) {
return std::tie(first.id, first.sourceId) < std::tie(second.id, second.sourceId);
std::ranges::sort(foundEntries, {}, [](const WatcherEntry &entry) {
return std::tie(entry.id, entry.sourceId);
});
std::vector<IdPaths> idPaths;
idPaths.reserve(foundEntries.size());
for (WatcherEntry entry : foundEntries) {
if (idPaths.empty() || idPaths.back().id != entry.id)
idPaths.emplace_back(entry.id, SourceIds{});
idPaths.back().sourceIds.push_back(entry.sourceId);
if (foundEntries.size()) {
idPaths.emplace_back(foundEntries.front().id, SourceIds{});
for (WatcherEntry entry : foundEntries) {
if (idPaths.back().id != entry.id)
idPaths.emplace_back(entry.id, SourceIds{});
idPaths.back().sourceIds.push_back(entry.sourceId);
}
}
return idPaths;

View File

@@ -40,11 +40,15 @@ public:
ProjectPartId id;
SourceType sourceType;
auto operator<=>(const ProjectChunkId &) const = default;
auto operator==(const ProjectChunkId &other) const
{
return std::tie(id, sourceType) == std::tie(other.id, other.sourceType);
}
friend bool operator<(ProjectChunkId first, ProjectPartId second) { return first.id < second; }
friend bool operator<(ProjectPartId first, ProjectChunkId second) { return first < second.id; }
auto operator<=>(const ProjectChunkId &other) const
{
return std::tie(id, sourceType) <=> std::tie(other.id, other.sourceType);
}
template<typename String>
friend void convertToString(String &string, const ProjectChunkId &id)
@@ -112,16 +116,6 @@ public:
<=> std::tie(second.sourceContextId, second.sourceId, second.id);
}
friend auto operator<=>(SourceContextId sourceContextId, WatcherEntry entry)
{
return sourceContextId <=> entry.sourceContextId;
}
friend auto operator<=>(WatcherEntry entry, SourceContextId sourceContextId)
{
return entry.sourceContextId <=> sourceContextId;
}
operator SourceId() const { return sourceId; }
operator SourceContextId() const { return sourceContextId; }