summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/clangsupport/filepathcache.h4
-rw-r--r--src/libs/clangsupport/stringcache.h77
-rw-r--r--tests/unit/unittest/mockmutex.h2
-rw-r--r--tests/unit/unittest/stringcache-test.cpp86
4 files changed, 121 insertions, 48 deletions
diff --git a/src/libs/clangsupport/filepathcache.h b/src/libs/clangsupport/filepathcache.h
index 61e8680965..553aed61f7 100644
--- a/src/libs/clangsupport/filepathcache.h
+++ b/src/libs/clangsupport/filepathcache.h
@@ -67,12 +67,12 @@ class FilePathCache final : private FilePathCacheBase
{
using DirectoryPathCache = StringCache<Utils::PathString,
int,
- std::mutex,
+ std::shared_timed_mutex,
decltype(&Utils::reverseCompare),
Utils::reverseCompare>;
using FileNameCache = StringCache<Utils::SmallString,
int,
- std::mutex,
+ std::shared_timed_mutex,
decltype(&Utils::compare),
Utils::compare>;
public:
diff --git a/src/libs/clangsupport/stringcache.h b/src/libs/clangsupport/stringcache.h
index d3de7fe4dd..c09fd199c1 100644
--- a/src/libs/clangsupport/stringcache.h
+++ b/src/libs/clangsupport/stringcache.h
@@ -33,7 +33,7 @@
#include <utils/smallstringfwd.h>
#include <algorithm>
-#include <mutex>
+#include <shared_mutex>
#include <vector>
namespace ClangBackEnd {
@@ -54,6 +54,8 @@ public:
NonLockingMutex& operator=(const NonLockingMutex&) = delete;
void lock() {}
void unlock() {}
+ void lock_shared() {}
+ void unlock_shared() {}
};
template <typename StringType, typename IndexType>
@@ -122,23 +124,34 @@ public:
IndexType stringId(Utils::SmallStringView stringView)
{
- std::lock_guard<Mutex> lock(m_mutex);
+ std::shared_lock<Mutex> sharedLock(m_mutex);
+ Found found = find(stringView);
+
+ if (found.wasFound)
+ return found.iterator->id;
+
+ sharedLock.unlock();
+ std::lock_guard<Mutex> exclusiveLock(m_mutex);
- return ungardedStringId(stringView);
+ found = find(stringView);
+ if (!found.wasFound) {
+ IndexType index = insertString(found.iterator, stringView, IndexType(m_indices.size()));
+ found.iterator = m_strings.begin() + index;;
+ }
+
+ return found.iterator->id;
}
template <typename Container>
std::vector<IndexType> stringIds(const Container &strings)
{
- std::lock_guard<Mutex> lock(m_mutex);
-
std::vector<IndexType> ids;
ids.reserve(strings.size());
std::transform(strings.begin(),
strings.end(),
std::back_inserter(ids),
- [&] (const auto &string) { return this->ungardedStringId(string); });
+ [&] (const auto &string) { return this->stringId(string); });
return ids;
}
@@ -150,7 +163,7 @@ public:
StringType string(IndexType id) const
{
- std::lock_guard<Mutex> lock(m_mutex);
+ std::shared_lock<Mutex> sharedLock(m_mutex);
return m_strings.at(m_indices.at(id)).string;
}
@@ -158,28 +171,25 @@ public:
template<typename Function>
StringType string(IndexType id, Function storageFunction)
{
- std::lock_guard<Mutex> lock(m_mutex);
+ std::shared_lock<Mutex> sharedLock(m_mutex);
- IndexType index;
+ if (IndexType(m_indices.size()) > id && m_indices.at(id) >= 0)
+ return m_strings.at(m_indices.at(id)).string;
- if (IndexType(m_indices.size()) <= id) {
- StringType string{storageFunction(id)};
- index = insertString(find(string).iterator, string, id);
- } else {
- index = m_indices.at(id);
- if (index < 0) {
- StringType string{storageFunction(id)};
- index = insertString(find(string).iterator, string, id);
- }
- }
+ sharedLock.unlock();
+ std::lock_guard<Mutex> exclusiveLock(m_mutex);
+ IndexType index;
+
+ StringType string{storageFunction(id)};
+ index = insertString(find(string).iterator, string, id);
- return m_strings.at(index).string;
+ return m_strings[index].string;
}
std::vector<StringType> strings(const std::vector<IndexType> &ids) const
{
- std::lock_guard<Mutex> lock(m_mutex);
+ std::shared_lock<Mutex> sharedLock(m_mutex);
std::vector<StringType> strings;
strings.reserve(ids.size());
@@ -200,12 +210,21 @@ public:
template<typename Function>
IndexType stringId(Utils::SmallStringView stringView, Function storageFunction)
{
- std::lock_guard<Mutex> lock(m_mutex);
+ std::shared_lock<Mutex> sharedLock(m_mutex);
Found found = find(stringView);
- if (!found.wasFound)
- insertString(found.iterator, stringView, storageFunction(stringView));
+ if (found.wasFound)
+ return found.iterator->id;
+
+ sharedLock.unlock();
+ std::lock_guard<Mutex> exclusiveLock(m_mutex);
+
+ found = find(stringView);
+ if (!found.wasFound) {
+ IndexType index = insertString(found.iterator, stringView, storageFunction(stringView));
+ found.iterator = m_strings.begin() + index;
+ }
return found.iterator->id;
}
@@ -216,16 +235,6 @@ public:
}
private:
- IndexType ungardedStringId(Utils::SmallStringView stringView)
- {
- Found found = find(stringView);
-
- if (!found.wasFound)
- insertString(found.iterator, stringView, IndexType(m_indices.size()));
-
- return found.iterator->id;
- }
-
Found find(Utils::SmallStringView stringView)
{
return findInSorted(m_strings.cbegin(), m_strings.cend(), stringView, compare);
diff --git a/tests/unit/unittest/mockmutex.h b/tests/unit/unittest/mockmutex.h
index cccb34e2ff..f922210392 100644
--- a/tests/unit/unittest/mockmutex.h
+++ b/tests/unit/unittest/mockmutex.h
@@ -34,4 +34,6 @@ public:
MOCK_METHOD0(lock, void ());
MOCK_METHOD0(unlock, void ());
+ MOCK_METHOD0(lock_shared, void ());
+ MOCK_METHOD0(unlock_shared, void ());
};
diff --git a/tests/unit/unittest/stringcache-test.cpp b/tests/unit/unittest/stringcache-test.cpp
index 1a20e473de..8465321c34 100644
--- a/tests/unit/unittest/stringcache-test.cpp
+++ b/tests/unit/unittest/stringcache-test.cpp
@@ -329,48 +329,110 @@ TEST_F(StringCache, FindInSortedFifeReverse)
ASSERT_TRUE(found.wasFound);
}
-TEST_F(StringCache, StringIdIsLocked)
+TEST_F(StringCache, StringIdIsReadAndWriteLockedForUnknownEntry)
{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
EXPECT_CALL(mockMutex, lock());
EXPECT_CALL(mockMutex, unlock());
cache.stringId("foo");
}
-TEST_F(StringCache, StringIdsIsLocked)
+TEST_F(StringCache, StringIdWithStorageFunctionIsReadAndWriteLockedForUnknownEntry)
{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("foo")));
EXPECT_CALL(mockMutex, unlock());
+ cache.stringId("foo", mockStorageFetchDirectyId);
+}
+
+TEST_F(StringCache, StringIdWithStorageFunctionIsReadLockedForKnownEntry)
+{
+ InSequence s;
+ cache.stringId("foo", mockStorageFetchDirectyId);
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
+ EXPECT_CALL(mockMutex, lock()).Times(0);
+ EXPECT_CALL(mockStorage, fetchDirectoryId(Eq("foo"))).Times(0);
+ EXPECT_CALL(mockMutex, unlock()).Times(0);
+
+ cache.stringId("foo", mockStorageFetchDirectyId);
+}
+
+TEST_F(StringCache, StringIdIsReadLockedForKnownEntry)
+{
+ cache.stringId("foo");
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
+ EXPECT_CALL(mockMutex, lock()).Times(0);
+ EXPECT_CALL(mockMutex, unlock()).Times(0);
+
+ cache.stringId("foo");
+}
+
+TEST_F(StringCache, StringIdsIsLocked)
+{
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
+
cache.stringIds({"foo"});
}
TEST_F(StringCache, StringIsLocked)
{
- cache.stringId("foo");
+ auto id = cache.stringId("foo");
- EXPECT_CALL(mockMutex, lock());
- EXPECT_CALL(mockMutex, unlock());
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
- cache.string(0);
+ cache.string(id);
}
TEST_F(StringCache, StringsIsLocked)
{
- cache.stringId("foo");
+ auto ids = cache.stringIds({"foo", "bar"});
- EXPECT_CALL(mockMutex, lock());
- EXPECT_CALL(mockMutex, unlock());
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
- cache.strings({0});
+ cache.strings(ids);
}
-TEST_F(StringCache, StringIdWithStorageFunctionIsLocked)
+TEST_F(StringCache, StringWithStorageFunctionIsReadAndWriteLockedForUnknownId)
{
+ InSequence s;
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
EXPECT_CALL(mockMutex, lock());
+ EXPECT_CALL(mockStorage, fetchDirectoryPath(Eq(41)));
EXPECT_CALL(mockMutex, unlock());
- cache.stringId("foo", mockStorageFetchDirectyId);
+ cache.string(41, mockStorageFetchDirectyPath);
+}
+
+TEST_F(StringCache, StringWithStorageFunctionIsReadLockedForKnownId)
+{
+ InSequence s;
+ cache.string(41, mockStorageFetchDirectyPath);
+
+ EXPECT_CALL(mockMutex, lock_shared());
+ EXPECT_CALL(mockMutex, unlock_shared());
+ EXPECT_CALL(mockMutex, lock()).Times(0);
+ EXPECT_CALL(mockStorage, fetchDirectoryPath(Eq(41))).Times(0);
+ EXPECT_CALL(mockMutex, unlock()).Times(0);
+
+ cache.string(41, mockStorageFetchDirectyPath);
}
TEST_F(StringCache, StringIdWithStorageFunctionWhichHasNoEntryIsCallingStorageFunction)