diff --git a/platform/default/sqlite_cache.cpp b/platform/default/sqlite_cache.cpp index 88bedec69..5816467aa 100644 --- a/platform/default/sqlite_cache.cpp +++ b/platform/default/sqlite_cache.cpp @@ -12,6 +12,9 @@ #include "sqlite3.hpp" #include +#include +#include + namespace { // The cache won't accept entries larger than this arbitrary size @@ -472,16 +475,31 @@ void SQLiteCache::Impl::refresh(const Resource& resource, Seconds expires) { } } +namespace { + +static std::mutex sharedMutex; +static std::unordered_map> shared; + +} // namespace + std::shared_ptr SQLiteCache::getShared(const std::string &path) { - std::shared_ptr temp = masterPtr.lock(); - if (!temp) { - temp.reset(new SQLiteCache(path)); - masterPtr = temp; + std::lock_guard lock(sharedMutex); + + std::shared_ptr cache; + + auto it = shared.find(path); + if (it != shared.end()) { + cache = it->second.lock(); + if (!cache) { + cache = std::make_shared(path); + it->second = cache; + } + } else { + cache = std::make_shared(path); + shared.emplace(path, cache); } - return temp; + return cache; } -std::weak_ptr SQLiteCache::masterPtr; - } // namespace mbgl diff --git a/src/mbgl/storage/sqlite_cache.hpp b/src/mbgl/storage/sqlite_cache.hpp index fd02765e7..64c683f4e 100644 --- a/src/mbgl/storage/sqlite_cache.hpp +++ b/src/mbgl/storage/sqlite_cache.hpp @@ -37,7 +37,6 @@ public: private: const std::unique_ptr> thread; - static std::weak_ptr masterPtr; }; } // namespace mbgl diff --git a/test/storage/cache_shared.cpp b/test/storage/cache_shared.cpp new file mode 100644 index 000000000..89ef3bfb8 --- /dev/null +++ b/test/storage/cache_shared.cpp @@ -0,0 +1,34 @@ +#include "storage.hpp" + +#include +#include +#include + +TEST_F(Storage, CacheShared) { + SCOPED_TEST(CacheShared) + using namespace mbgl; + + util::RunLoop loop; + + // Check that we're getting two different caches when we request different paths. + auto memory = SQLiteCache::getShared(); + auto file = SQLiteCache::getShared("test/fixtures/database/cache.db"); + EXPECT_NE(memory.get(), file.get()); + EXPECT_EQ(memory.get(), SQLiteCache::getShared().get()); + + // Store a response into the memory file cache, then delete the last reference. + const Resource resource { Resource::Kind::Unknown, "http://example.com" }; + memory->put(resource, Response()); + memory.reset(); + + // Now check that the original memory file cache has been destructed and that it doesn't contain + // the information we put into it. + memory = SQLiteCache::getShared(); + auto req = memory->get(resource, [&](std::unique_ptr res) { + EXPECT_FALSE(res.get()); + CacheShared.finish(); + loop.stop(); + }); + + loop.run(); +} diff --git a/test/test.gypi b/test/test.gypi index 21b203887..607dd2b76 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -70,6 +70,7 @@ 'storage/storage.cpp', 'storage/cache_response.cpp', 'storage/cache_revalidate.cpp', + 'storage/cache_shared.cpp', 'storage/cache_size.cpp', 'storage/database.cpp', 'storage/asset_file_source.cpp',