зеркало из https://github.com/microsoft/L4.git
Support GCC 6.2. (#9)
This commit is contained in:
Родитель
a2337ff44e
Коммит
3b1648fc1a
|
@ -0,0 +1,59 @@
|
|||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(L4 CXX)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
message(FATAL_ERROR "Use provided solution file.")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
add_compile_options(-std=c++14)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||
find_package(Boost 1.45.0 COMPONENTS unit_test_framework REQUIRED)
|
||||
|
||||
if(Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/inc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/inc/L4)
|
||||
|
||||
# Need to expand the followings for installation.
|
||||
set(L4_HEADERS
|
||||
inc/L4/Utils/MurmurHash3.h)
|
||||
|
||||
set(L4_SOURCES
|
||||
src/EpochActionManager.cpp
|
||||
src/MurmurHash3.cpp
|
||||
src/PerfLogger.cpp)
|
||||
|
||||
add_library(L4
|
||||
${L4_SOURCES}
|
||||
${L4_HEADERS})
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_executable(L4.UnitTests
|
||||
Unittests/CacheHashTableTest.cpp
|
||||
Unittests/EpochManagerTest.cpp
|
||||
Unittests/HashTableManagerTest.cpp
|
||||
Unittests/HashTableRecordTest.cpp
|
||||
Unittests/HashTableServiceTest.cpp
|
||||
Unittests/PerfInfoTest.cpp
|
||||
Unittests/ReadWriteHashTableSerializerTest.cpp
|
||||
Unittests/ReadWriteHashTableTest.cpp
|
||||
Unittests/SettingAdapterTest.cpp
|
||||
Unittests/Utils.cpp
|
||||
Unittests/UtilsTest.cpp
|
||||
Unittests/Main.cpp)
|
||||
|
||||
target_link_libraries(L4.UnitTests
|
||||
L4
|
||||
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
|
||||
-lpthread)
|
||||
#${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
add_test(NAME L4UnitTests COMMAND L4.UnitTests)
|
|
@ -1,4 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include "Utils.h"
|
||||
#include "Mocks.h"
|
||||
#include "CheckedAllocator.h"
|
||||
|
@ -6,9 +8,6 @@
|
|||
#include "L4/HashTable/Cache/Metadata.h"
|
||||
#include "L4/HashTable/Cache/HashTable.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace L4
|
||||
{
|
||||
namespace UnitTests
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "Utils.h"
|
||||
#include "L4/Interprocess/Connection/ConnectionMonitor.h"
|
||||
#include "L4/Interprocess/Connection/EndPointInfoUtils.h"
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "stdafx.h"
|
||||
#include <atomic>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Utils.h"
|
||||
#include "L4/Epoch/EpochQueue.h"
|
||||
#include "L4/Epoch/EpochActionManager.h"
|
||||
#include "L4/LocalMemory/EpochManager.h"
|
||||
#include "L4/Log/PerfCounter.h"
|
||||
#include "L4/Utils/Lock.h"
|
||||
#include <atomic>
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
@ -150,7 +150,7 @@ BOOST_AUTO_TEST_CASE(EpochManagerTest)
|
|||
EpochManagerConfig(100000U, std::chrono::milliseconds(5U), 1U),
|
||||
perfData);
|
||||
|
||||
std::atomic<bool> isActionCalled = false;
|
||||
std::atomic<bool> isActionCalled{ false };
|
||||
auto action = [&]() { isActionCalled = true; };
|
||||
|
||||
auto epochCounterReferenced = epochManager.GetEpochRefManager().AddRef();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Utils.h"
|
||||
#include "Mocks.h"
|
||||
#include "L4/HashTable/Config.h"
|
||||
|
@ -125,4 +125,4 @@ BOOST_AUTO_TEST_CASE(HashTableManagerTestForSerialzation)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "L4/HashTable/Common/Record.h"
|
||||
#include "Utils.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "L4/HashTable/Common/Record.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ protected:
|
|||
|
||||
Validate(
|
||||
RecordSerializer{
|
||||
isFixedKey ? static_cast<RecordSerializer::KeySize>(key.size()) : 0U,
|
||||
isFixedKey ? static_cast<RecordSerializer::KeySize>(key.size()) : std::uint16_t(0),
|
||||
isFixedValue ? static_cast<RecordSerializer::ValueSize>(value.size()) : 0U,
|
||||
useMetaValue ? static_cast<RecordSerializer::ValueSize>(metaValue.size()) : 0U },
|
||||
key,
|
||||
|
@ -160,4 +160,4 @@ BOOST_AUTO_TEST_CASE(InvalidSizeTest)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "Mocks.h"
|
||||
#include "Utils.h"
|
||||
#include "L4/LocalMemory/HashTableService.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
@ -49,4 +49,4 @@ BOOST_AUTO_TEST_CASE(HashTableServiceTest)
|
|||
}
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
#pragma once
|
||||
|
||||
#define BOOST_TEST_MODULE L4Unittests
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "L4/Epoch/IEpochActionManager.h"
|
||||
#include "L4/Log/PerfLogger.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "L4/Log/PerfLogger.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <limits>
|
||||
#include "L4/Log/PerfLogger.h"
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
@ -101,4 +101,4 @@ BOOST_AUTO_TEST_CASE(PerfDataTest)
|
|||
}
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include "Utils.h"
|
||||
#include "Mocks.h"
|
||||
#include "L4/HashTable/ReadWrite/HashTable.h"
|
||||
#include "L4/HashTable/ReadWrite/Serializer.h"
|
||||
#include "L4/Log/PerfCounter.h"
|
||||
#include "L4/LocalMemory/Memory.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
@ -176,4 +176,4 @@ BOOST_AUTO_TEST_CASE(HashTableSerializeTest)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Utils.h"
|
||||
#include "Mocks.h"
|
||||
#include "CheckedAllocator.h"
|
||||
|
@ -673,4 +673,4 @@ BOOST_AUTO_TEST_CASE(HashTableIteratorTest)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "L4/HashTable/Common/SettingAdapter.h"
|
||||
#include "L4/HashTable/Common/Record.h"
|
||||
#include "CheckedAllocator.h"
|
||||
|
@ -38,4 +38,4 @@ BOOST_AUTO_TEST_CASE(SettingAdapterTestWithNonDefaultValues)
|
|||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace UnitTests
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
</Lib>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)Unittests;$(SolutionDir)inc;$(SolutionDir)inc/L4;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalOptions>/Zm136 %(AdditionalOptions)</AdditionalOptions>
|
||||
<PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
|
||||
|
@ -60,16 +59,13 @@
|
|||
<ClCompile Include="PerfInfoTest.cpp" />
|
||||
<ClCompile Include="ReadWriteHashTableTest.cpp" />
|
||||
<ClCompile Include="SettingAdapterTest.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="UtilsTest.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CheckedAllocator.h" />
|
||||
<ClInclude Include="Mocks.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HashTableServiceTest.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -50,6 +47,9 @@
|
|||
<ClCompile Include="ConnectionMonitorTest.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Utils.h">
|
||||
|
@ -61,9 +61,6 @@
|
|||
<ClInclude Include="CheckedAllocator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "Utils.h"
|
||||
|
||||
namespace L4
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include "L4/Log/PerfCounter.h"
|
||||
#include "L4/Utils/Exception.h"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "L4/Utils/Math.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <array>
|
||||
#include "L4/Utils/Math.h"
|
||||
|
||||
namespace L4
|
||||
{
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "stdafx.h"
|
|
@ -32,7 +32,7 @@ public:
|
|||
: m_frontIndex{ epochCounter }
|
||||
, m_backIndex{ epochCounter }
|
||||
, m_mutexForBackIndex{}
|
||||
, m_refCounts{ queueSize, Allocator::rebind<RefCount>::other(allocator) }
|
||||
, m_refCounts{ queueSize, typename Allocator::template rebind<RefCount>::other(allocator) }
|
||||
{
|
||||
if (queueSize == 0U)
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
std::uint64_t AddRef()
|
||||
{
|
||||
// The synchronization is needed for EpochCounterManager::AddNewEpoch().
|
||||
EpochQueue::SharableLock lock(m_epochQueue.m_mutexForBackIndex);
|
||||
typename EpochQueue::SharableLock lock(m_epochQueue.m_mutexForBackIndex);
|
||||
|
||||
++m_epochQueue.m_refCounts[m_epochQueue.m_backIndex % m_epochQueue.m_refCounts.size()];
|
||||
|
||||
|
@ -126,7 +126,7 @@ public:
|
|||
void AddNewEpoch()
|
||||
{
|
||||
// The synchronization is needed for EpochRefManager::AddRef().
|
||||
EpochQueue::ExclusiveLock lock(m_epochQueue.m_mutexForBackIndex);
|
||||
typename EpochQueue::ExclusiveLock lock(m_epochQueue.m_mutexForBackIndex);
|
||||
|
||||
++m_epochQueue.m_backIndex;
|
||||
|
||||
|
@ -162,4 +162,4 @@ private:
|
|||
EpochQueue& m_epochQueue;
|
||||
};
|
||||
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include "detail/ToRawPointer.h"
|
||||
#include "Epoch/IEpochActionManager.h"
|
||||
#include "HashTable/IHashTable.h"
|
||||
|
@ -28,17 +29,21 @@ public:
|
|||
using Base = ReadWrite::ReadOnlyHashTable<Allocator>;
|
||||
using HashTable = typename Base::HashTable;
|
||||
|
||||
using Key = typename Base::Key;
|
||||
using Value = typename Base::Value;
|
||||
using IIteratorPtr = typename Base::IIteratorPtr;
|
||||
|
||||
class Iterator;
|
||||
|
||||
ReadOnlyHashTable(
|
||||
HashTable& hashTable,
|
||||
std::chrono::seconds recordTimeToLive)
|
||||
: Base{
|
||||
: Base(
|
||||
hashTable,
|
||||
RecordSerializer{
|
||||
hashTable.m_setting.m_fixedKeySize,
|
||||
hashTable.m_setting.m_fixedValueSize,
|
||||
Metadata::c_metaDataSize } }
|
||||
Metadata::c_metaDataSize })
|
||||
, m_recordTimeToLive{ recordTimeToLive }
|
||||
{}
|
||||
|
||||
|
@ -47,7 +52,7 @@ public:
|
|||
const auto status = GetInternal(key, value);
|
||||
|
||||
// Note that the following const_cast is safe and necessary to update cache hit information.
|
||||
const_cast<HashTablePerfData&>(GetPerfData()).Increment(
|
||||
const_cast<HashTablePerfData&>(this->GetPerfData()).Increment(
|
||||
status
|
||||
? HashTablePerfCounter::CacheHitCount
|
||||
: HashTablePerfCounter::CacheMissCount);
|
||||
|
@ -58,10 +63,10 @@ public:
|
|||
virtual IIteratorPtr GetIterator() const override
|
||||
{
|
||||
return std::make_unique<Iterator>(
|
||||
m_hashTable,
|
||||
m_recordSerializer,
|
||||
this->m_hashTable,
|
||||
this->m_recordSerializer,
|
||||
m_recordTimeToLive,
|
||||
GetCurrentEpochTime());
|
||||
this->GetCurrentEpochTime());
|
||||
}
|
||||
|
||||
ReadOnlyHashTable(const ReadOnlyHashTable&) = delete;
|
||||
|
@ -80,7 +85,7 @@ protected:
|
|||
// If the record with the given key is found, check if the record is expired or not.
|
||||
// Note that the following const_cast is safe and necessary to update the access status.
|
||||
Metadata metaData{ const_cast<std::uint32_t*>(reinterpret_cast<const std::uint32_t*>(value.m_data)) };
|
||||
if (metaData.IsExpired(GetCurrentEpochTime(), m_recordTimeToLive))
|
||||
if (metaData.IsExpired(this->GetCurrentEpochTime(), m_recordTimeToLive))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -101,27 +106,27 @@ template <typename Allocator, typename Clock>
|
|||
class ReadOnlyHashTable<Allocator, Clock>::Iterator : public Base::Iterator
|
||||
{
|
||||
public:
|
||||
using Base = typename Base::Iterator;
|
||||
using BaseIterator = typename Base::Iterator;
|
||||
|
||||
Iterator(
|
||||
const HashTable& hashTable,
|
||||
const RecordSerializer& recordDeserializer,
|
||||
std::chrono::seconds recordTimeToLive,
|
||||
std::chrono::seconds currentEpochTime)
|
||||
: Base(hashTable, recordDeserializer)
|
||||
: BaseIterator(hashTable, recordDeserializer)
|
||||
, m_recordTimeToLive{ recordTimeToLive }
|
||||
, m_currentEpochTime{ currentEpochTime }
|
||||
{}
|
||||
|
||||
Iterator(Iterator&& other)
|
||||
: Base(std::move(other))
|
||||
: BaseIterator(std::move(other))
|
||||
, m_recordTimeToLive{ std::move(other.m_recordTimeToLive) }
|
||||
, m_currentEpochTime{ std::move(other.m_currentEpochTime) }
|
||||
{}
|
||||
|
||||
bool MoveNext() override
|
||||
{
|
||||
if (!Base::MoveNext())
|
||||
if (!BaseIterator::MoveNext())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -131,20 +136,20 @@ public:
|
|||
const Metadata metaData{
|
||||
const_cast<std::uint32_t*>(
|
||||
reinterpret_cast<const std::uint32_t*>(
|
||||
Base::GetValue().m_data)) };
|
||||
BaseIterator::GetValue().m_data)) };
|
||||
|
||||
if (!metaData.IsExpired(m_currentEpochTime, m_recordTimeToLive))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} while (Base::MoveNext());
|
||||
} while (BaseIterator::MoveNext());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Value GetValue() const override
|
||||
{
|
||||
auto value = Base::GetValue();
|
||||
auto value = BaseIterator::GetValue();
|
||||
value.m_data += Metadata::c_metaDataSize;
|
||||
value.m_size -= Metadata::c_metaDataSize;
|
||||
|
||||
|
@ -174,6 +179,10 @@ public:
|
|||
using WritableBase = typename ReadWrite::WritableHashTable<Allocator>;
|
||||
using HashTable = typename ReadOnlyBase::HashTable;
|
||||
|
||||
using Key = typename ReadOnlyBase::Key;
|
||||
using Value = typename ReadOnlyBase::Value;
|
||||
using ISerializerPtr = typename WritableBase::ISerializerPtr;
|
||||
|
||||
WritableHashTable(
|
||||
HashTable& hashTable,
|
||||
IEpochActionManager& epochManager,
|
||||
|
@ -210,7 +219,7 @@ public:
|
|||
|
||||
virtual ISerializerPtr GetSerializer() const override
|
||||
{
|
||||
throw std::exception("Not implemented yet.");
|
||||
throw std::runtime_error("Not implemented yet.");
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -219,13 +228,13 @@ private:
|
|||
|
||||
void EvictBasedOnTime(const Key& key)
|
||||
{
|
||||
const auto bucketIndex = GetBucketInfo(key).first;
|
||||
const auto bucketIndex = this->GetBucketInfo(key).first;
|
||||
|
||||
auto* entry = &m_hashTable.m_buckets[bucketIndex];
|
||||
auto* entry = &(this->m_hashTable.m_buckets[bucketIndex]);
|
||||
|
||||
const auto curEpochTime = GetCurrentEpochTime();
|
||||
const auto curEpochTime = this->GetCurrentEpochTime();
|
||||
|
||||
HashTable::Lock lock{ m_hashTable.GetMutex(bucketIndex) };
|
||||
typename HashTable::Lock lock{ this->m_hashTable.GetMutex(bucketIndex) };
|
||||
|
||||
while (entry != nullptr)
|
||||
{
|
||||
|
@ -238,12 +247,12 @@ private:
|
|||
const Metadata metadata{
|
||||
const_cast<std::uint32_t*>(
|
||||
reinterpret_cast<const std::uint32_t*>(
|
||||
m_recordSerializer.Deserialize(*data).m_value.m_data)) };
|
||||
this->m_recordSerializer.Deserialize(*data).m_value.m_data)) };
|
||||
|
||||
if (metadata.IsExpired(curEpochTime, m_recordTimeToLive))
|
||||
if (metadata.IsExpired(curEpochTime, this->m_recordTimeToLive))
|
||||
{
|
||||
WritableBase::Remove(*entry, i);
|
||||
m_hashTable.m_perfData.Increment(HashTablePerfCounter::EvictedRecordsCount);
|
||||
this->m_hashTable.m_perfData.Increment(HashTablePerfCounter::EvictedRecordsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,12 +281,12 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
const auto curEpochTime = GetCurrentEpochTime();
|
||||
const auto curEpochTime = this->GetCurrentEpochTime();
|
||||
|
||||
// The max number of iterations we are going through per eviction is twice the number
|
||||
// of buckets so that it can clear the access status. Note that this is the worst
|
||||
// case scenario and the eviction process should exit much quicker in a normal case.
|
||||
auto& buckets = m_hashTable.m_buckets;
|
||||
auto& buckets = this->m_hashTable.m_buckets;
|
||||
std::uint64_t numIterationsRemaining = buckets.size() * 2U;
|
||||
|
||||
while (numBytesToFree > 0U && numIterationsRemaining-- > 0U)
|
||||
|
@ -287,8 +296,8 @@ private:
|
|||
|
||||
// Lock the bucket since another thread can bypass Evict() since TotalDataSize can
|
||||
// be updated before the lock on m_evictMutex is released.
|
||||
HashTable::UniqueLock lock{ m_hashTable.GetMutex(currentBucketIndex) };
|
||||
HashTable::Entry* entry = &bucket;
|
||||
typename HashTable::UniqueLock lock{ this->m_hashTable.GetMutex(currentBucketIndex) };
|
||||
typename HashTable::Entry* entry = &bucket;
|
||||
|
||||
while (entry != nullptr)
|
||||
{
|
||||
|
@ -298,7 +307,7 @@ private:
|
|||
|
||||
if (data != nullptr)
|
||||
{
|
||||
const auto record = m_recordSerializer.Deserialize(*data);
|
||||
const auto record = this->m_recordSerializer.Deserialize(*data);
|
||||
const auto& value = record.m_value;
|
||||
|
||||
Metadata metadata{
|
||||
|
@ -309,7 +318,7 @@ private:
|
|||
// Evict this record if
|
||||
// 1: the record is expired, or
|
||||
// 2: the entry is not recently accessed (and unset the access bit if set).
|
||||
if (metadata.IsExpired(curEpochTime, m_recordTimeToLive)
|
||||
if (metadata.IsExpired(curEpochTime, this->m_recordTimeToLive)
|
||||
|| !metadata.UpdateAccessStatus(false))
|
||||
{
|
||||
const auto numBytesFreed = record.m_key.m_size + value.m_size;
|
||||
|
@ -317,7 +326,7 @@ private:
|
|||
|
||||
WritableBase::Remove(*entry, i);
|
||||
|
||||
m_hashTable.m_perfData.Increment(HashTablePerfCounter::EvictedRecordsCount);
|
||||
this->m_hashTable.m_perfData.Increment(HashTablePerfCounter::EvictedRecordsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -357,15 +366,15 @@ private:
|
|||
|
||||
RecordBuffer* CreateRecordBuffer(const Key& key, const Value& value)
|
||||
{
|
||||
const auto bufferSize = m_recordSerializer.CalculateBufferSize(key, value);
|
||||
const auto bufferSize = this->m_recordSerializer.CalculateBufferSize(key, value);
|
||||
auto buffer = Detail::to_raw_pointer(
|
||||
m_hashTable.GetAllocator<std::uint8_t>().allocate(bufferSize));
|
||||
this->m_hashTable.template GetAllocator<std::uint8_t>().allocate(bufferSize));
|
||||
|
||||
std::uint32_t metaDataBuffer;
|
||||
Metadata{ &metaDataBuffer, GetCurrentEpochTime() };
|
||||
Metadata{ &metaDataBuffer, this->GetCurrentEpochTime() };
|
||||
|
||||
// 4-byte Metadata is inserted between key and value buffer.
|
||||
return m_recordSerializer.Serialize(
|
||||
return this->m_recordSerializer.Serialize(
|
||||
key,
|
||||
value,
|
||||
Value{ reinterpret_cast<std::uint8_t*>(&metaDataBuffer), sizeof(metaDataBuffer) },
|
||||
|
|
|
@ -385,7 +385,7 @@ protected:
|
|||
curEntry->m_next.Store(
|
||||
new (Detail::to_raw_pointer(
|
||||
this->m_hashTable.template GetAllocator<typename HashTable::Entry>().allocate(1U)))
|
||||
HashTable::Entry(),
|
||||
typename HashTable::Entry(),
|
||||
std::memory_order_release);
|
||||
|
||||
stat.m_isNewEntryAdded = true;
|
||||
|
|
|
@ -103,10 +103,10 @@ public:
|
|||
{
|
||||
DeserializerHelper helper(stream);
|
||||
|
||||
HashTable::Setting setting;
|
||||
typename HashTable::Setting setting;
|
||||
helper.Deserialize(setting);
|
||||
|
||||
auto hashTable{ memory.MakeUnique<HashTable>(
|
||||
auto hashTable{ memory.template MakeUnique<HashTable>(
|
||||
setting,
|
||||
memory.GetAllocator()) };
|
||||
|
||||
|
|
|
@ -9,18 +9,18 @@ namespace L4
|
|||
namespace LocalMemory
|
||||
{
|
||||
|
||||
class Context : private EpochRefPolicy<EpochManager::EpochRefManager>
|
||||
class Context : private EpochRefPolicy<EpochManager::TheEpochRefManager>
|
||||
{
|
||||
public:
|
||||
Context(
|
||||
HashTableManager& hashTableManager,
|
||||
EpochManager::EpochRefManager& epochRefManager)
|
||||
: EpochRefPolicy<EpochManager::EpochRefManager>(epochRefManager)
|
||||
EpochManager::TheEpochRefManager& epochRefManager)
|
||||
: EpochRefPolicy<EpochManager::TheEpochRefManager>(epochRefManager)
|
||||
, m_hashTableManager{ hashTableManager }
|
||||
{}
|
||||
|
||||
Context(Context&& context)
|
||||
: EpochRefPolicy<EpochManager::EpochRefManager>(std::move(context))
|
||||
: EpochRefPolicy<EpochManager::TheEpochRefManager>(std::move(context))
|
||||
, m_hashTableManager{ context.m_hashTableManager }
|
||||
{}
|
||||
|
||||
|
@ -52,4 +52,4 @@ private:
|
|||
};
|
||||
|
||||
} // namespace LocalMemory
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -20,11 +20,11 @@ namespace LocalMemory
|
|||
class EpochManager : public IEpochActionManager
|
||||
{
|
||||
public:
|
||||
using EpochQueue = EpochQueue<
|
||||
using TheEpochQueue = EpochQueue<
|
||||
boost::shared_lock_guard<Utils::ReaderWriterLockSlim>,
|
||||
std::lock_guard<Utils::ReaderWriterLockSlim>>;
|
||||
|
||||
using EpochRefManager = EpochRefManager<EpochQueue>;
|
||||
using TheEpochRefManager = EpochRefManager<TheEpochQueue>;
|
||||
|
||||
EpochManager(
|
||||
const EpochManagerConfig& config,
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
}}
|
||||
{}
|
||||
|
||||
EpochRefManager& GetEpochRefManager()
|
||||
TheEpochRefManager& GetEpochRefManager()
|
||||
{
|
||||
return m_epochRefManager;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
EpochManager& operator=(const EpochManager&) = delete;
|
||||
|
||||
private:
|
||||
using EpochCounterManager = EpochCounterManager<EpochQueue>;
|
||||
using TheEpochCounterManager = EpochCounterManager<TheEpochQueue>;
|
||||
|
||||
using ProcessingThread = Utils::RunningThread<std::function<void()>>;
|
||||
|
||||
|
@ -100,16 +100,20 @@ private:
|
|||
EpochManagerConfig m_config;
|
||||
|
||||
// The global current epoch counter.
|
||||
#if defined(_MSC_VER)
|
||||
std::atomic_uint64_t m_currentEpochCounter;
|
||||
#else
|
||||
std::atomic<std::uint64_t> m_currentEpochCounter;
|
||||
#endif
|
||||
|
||||
// Epoch queue.
|
||||
EpochQueue m_epochQueue;
|
||||
TheEpochQueue m_epochQueue;
|
||||
|
||||
// Handles adding/decrementing ref counts.
|
||||
EpochRefManager m_epochRefManager;
|
||||
TheEpochRefManager m_epochRefManager;
|
||||
|
||||
// Handles adding new epoch and finding the epoch counts that have zero ref counts.
|
||||
EpochCounterManager m_epochCounterManager;
|
||||
TheEpochCounterManager m_epochCounterManager;
|
||||
|
||||
// Handles registering/performing actions.
|
||||
EpochActionManager m_epochActionManager;
|
||||
|
@ -121,4 +125,4 @@ private:
|
|||
};
|
||||
|
||||
} // namespace LocalMemory
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
|
@ -42,8 +42,8 @@ public:
|
|||
|
||||
using namespace HashTable;
|
||||
|
||||
using InternalHashTable = ReadWrite::WritableHashTable<Allocator>::HashTable;
|
||||
using Memory = LocalMemory::Memory<Allocator>;
|
||||
using InternalHashTable = typename ReadWrite::WritableHashTable<Allocator>::HashTable;
|
||||
using Memory = typename LocalMemory::Memory<Allocator>;
|
||||
|
||||
Memory memory{ allocator };
|
||||
|
||||
|
@ -53,8 +53,8 @@ public:
|
|||
Deserialize(
|
||||
memory,
|
||||
*(serializerConfig->m_stream))
|
||||
: memory.MakeUnique<InternalHashTable>(
|
||||
InternalHashTable::Setting{
|
||||
: memory.template MakeUnique<InternalHashTable>(
|
||||
typename InternalHashTable::Setting{
|
||||
config.m_setting.m_numBuckets,
|
||||
(std::max)(config.m_setting.m_numBucketsPerMutex.get_value_or(1U), 1U),
|
||||
config.m_setting.m_fixedKeySize.get_value_or(0U),
|
||||
|
@ -103,4 +103,4 @@ private:
|
|||
};
|
||||
|
||||
} // namespace LocalMemory
|
||||
} // namespace L4
|
||||
} // namespace L4
|
||||
|
|
Загрузка…
Ссылка в новой задаче