From 92884b48bacb8cc40d16cf514a9b029f4fdd474f Mon Sep 17 00:00:00 2001 From: tatiana-yan Date: Fri, 7 Feb 2020 14:52:02 +0300 Subject: [PATCH] [coding] Add threadsafe get to MapUint32ToValue. --- .../coding_tests/map_uint32_to_val_tests.cpp | 2 + coding/map_uint32_to_val.hpp | 57 ++++++++++++++----- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/coding/coding_tests/map_uint32_to_val_tests.cpp b/coding/coding_tests/map_uint32_to_val_tests.cpp index 0066b602e3..adf9ec1c2e 100644 --- a/coding/coding_tests/map_uint32_to_val_tests.cpp +++ b/coding/coding_tests/map_uint32_to_val_tests.cpp @@ -55,6 +55,8 @@ UNIT_TEST(MapUint32ValTest) uint32_t res; TEST(table->Get(d.first, res), ()); TEST_EQUAL(res, d.second, ()); + TEST(table->GetThreadsafe(d.first, res), ()); + TEST_EQUAL(res, d.second, ()); } } } diff --git a/coding/map_uint32_to_val.hpp b/coding/map_uint32_to_val.hpp index 3e7c9f818c..f719bc2e23 100644 --- a/coding/map_uint32_to_val.hpp +++ b/coding/map_uint32_to_val.hpp @@ -65,7 +65,10 @@ // exception of the last one) is a sequence of kBlockSize variables // encoded by block encoding callback. // -// On Get call kBlockSize consecutive variables are decoded and cached in RAM. +// On Get call kBlockSize consecutive variables are decoded and cached in RAM. Get is not +// threadsafe. +// +// GetThreadsafe does not use cache. template class MapUint32ToValue @@ -162,23 +165,23 @@ public: auto & entry = m_cache[base]; if (entry.empty()) - { - entry.resize(kBlockSize); + entry = GetImpl(id); - auto const start = m_offsets.select(base); - auto const end = base + 1 < m_offsets.num_ones() - ? m_offsets.select(base + 1) - : m_header.m_endOffset - m_header.m_variablesOffset; + value = entry[offset]; + return true; + } - std::vector data(static_cast(end - start)); + // Tries to get |value| for key identified by |id|. Returns + // false if table does not have entry for this id. + WARN_UNUSED_RESULT bool GetThreadsafe(uint32_t id, Value & value) const + { + if (id >= m_ids.size() || !m_ids[id]) + return false; - m_reader.Read(m_header.m_variablesOffset + start, data.data(), data.size()); + uint32_t const rank = static_cast(m_ids.rank(id)); + uint32_t const offset = rank % kBlockSize; - MemReader mreader(data.data(), data.size()); - NonOwningReaderSource msource(mreader); - - m_readBlockCallback(msource, kBlockSize, entry); - } + auto const entry = GetImpl(id); value = entry[offset]; return true; @@ -219,6 +222,32 @@ public: uint64_t Count() const { return m_ids.num_ones(); } private: + std::vector GetImpl(uint32_t id) const + { + ASSERT_LESS(id, m_ids.size(), ()); + ASSERT(m_ids[id], ()); + + uint32_t const rank = static_cast(m_ids.rank(id)); + uint32_t const base = rank / kBlockSize; + + std::vector values(kBlockSize); + + auto const start = m_offsets.select(base); + auto const end = base + 1 < m_offsets.num_ones() + ? m_offsets.select(base + 1) + : m_header.m_endOffset - m_header.m_variablesOffset; + + std::vector data(static_cast(end - start)); + + m_reader.Read(m_header.m_variablesOffset + start, data.data(), data.size()); + + MemReader mreader(data.data(), data.size()); + NonOwningReaderSource msource(mreader); + + m_readBlockCallback(msource, kBlockSize, values); + return values; + } + bool Init() { m_header.Read(m_reader);