diff --git a/benchmark/source/BenchmarkHash.cpp b/benchmark/source/BenchmarkHash.cpp index d5bc8fc6..35470e76 100644 --- a/benchmark/source/BenchmarkHash.cpp +++ b/benchmark/source/BenchmarkHash.cpp @@ -12,32 +12,9 @@ #include -// STD_HASH_SUPPORTED -// -// Defined as 0 or 1. identifies if hash_map (pre-C++11 container type) is supported. -// -#ifndef STD_HASH_SUPPORTED - // Apache STL doesn't have any kind of hash containers. - #if defined(_RWSTD_VER_STR) - #define STD_HASH_SUPPORTED 0 - #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) // To consider: Find a better way to identify the switchover from pre-C++11 hash containers to C++11 hash containers. - #define STD_HASH_SUPPORTED 0 // Need to use std::unordered_map, etc. instead of hash_map, etc. - #elif defined(EA_COMPILER_CLANG) && (EA_COMPILER_CPP11_ENABLED) // Bad way to determine if we have C++11 hash containers - #define STD_HASH_SUPPORTED 0 - #else - #define STD_HASH_SUPPORTED 1 - #endif -#endif - EA_DISABLE_ALL_VC_WARNINGS() -#if STD_HASH_SUPPORTED - #if (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) && (defined(_CXXCONFIG) || defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_MINGW)) - #include - #else - #include - #endif -#endif +#include #include #include #include @@ -79,46 +56,11 @@ struct HashString8 }; -#if STD_HASH_SUPPORTED - #if defined(_STLPORT_VERSION) // STLPort is an modular add-on that can override any other STL. - typedef std::hash_map StdMapUint32TO; - typedef eastl::hash_map EaMapUint32TO; - - typedef std::hash_map > StdMapStrUint32; - typedef eastl::hash_map > EaMapStrUint32; - - #elif defined(_MSC_VER) - typedef stdext::hash_map StdMapUint32TO; - typedef eastl::hash_map EaMapUint32TO; - - typedef stdext::hash_map > StdMapStrUint32; - typedef eastl::hash_map > EaMapStrUint32; - - #elif defined(_CPPLIB_VER) // Dinkumware STL. - typedef std::hash_map StdMapUint32TO; - typedef eastl::hash_map EaMapUint32TO; - - typedef std::hash_map > StdMapStrUint32; - typedef eastl::hash_map > EaMapStrUint32; - - #elif defined(__GNUC__) && (defined(_CXXCONFIG) || defined(_GLIBCXX_STD) || defined(EA_PLATFORM_UNIX)) // GCC using libstdc++ - typedef __gnu_cxx::hash_map StdMapUint32TO; - typedef eastl::hash_map EaMapUint32TO; - - typedef __gnu_cxx::hash_map > StdMapStrUint32; - typedef eastl::hash_map > EaMapStrUint32; - - #else // Else generic hash map similar to that proposed for the C++ standard. - typedef std::hash_map StdMapUint32TO; - typedef eastl::hash_map EaMapUint32TO; - - typedef std::hash_map > StdMapStrUint32; - typedef eastl::hash_map > EaMapStrUint32; - - #endif -#endif - +using StdMapUint32TO = std::unordered_map; +using StdMapStrUint32 = std::unordered_map>; +using EaMapUint32TO = eastl::hash_map; +using EaMapStrUint32 = eastl::hash_map>; namespace @@ -291,225 +233,221 @@ namespace void BenchmarkHash() { - #if STD_HASH_SUPPORTED - EASTLTest_Printf("HashMap\n"); + EASTLTest_Printf("HashMap\n"); - EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed()); - EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles); - EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles); + EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed()); + EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles); + EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles); - { - eastl::vector< std::pair > stdVectorUT(10000); - eastl::vector< eastl::pair > eaVectorUT(10000); + { + eastl::vector< std::pair > stdVectorUT(10000); + eastl::vector< eastl::pair > eaVectorUT(10000); - eastl::vector< std::pair< std::string, uint32_t> > stdVectorSU(10000); - eastl::vector< eastl::pair > eaVectorSU(10000); + eastl::vector< std::pair< std::string, uint32_t> > stdVectorSU(10000); + eastl::vector< eastl::pair > eaVectorSU(10000); - for(eastl_size_t i = 0, iEnd = stdVectorUT.size(); i < iEnd; i++) - { - const uint32_t n1 = rng.RandLimit((uint32_t)(iEnd / 2)); - const uint32_t n2 = rng.RandValue(); + for(eastl_size_t i = 0, iEnd = stdVectorUT.size(); i < iEnd; i++) + { + const uint32_t n1 = rng.RandLimit((uint32_t)(iEnd / 2)); + const uint32_t n2 = rng.RandValue(); - stdVectorUT[i] = std::pair(n1, TestObject(n2)); - eaVectorUT[i] = eastl::pair(n1, TestObject(n2)); + stdVectorUT[i] = std::pair(n1, TestObject(n2)); + eaVectorUT[i] = eastl::pair(n1, TestObject(n2)); - char str_n1[32]; - sprintf(str_n1, "%u", (unsigned)n1); + char str_n1[32]; + sprintf(str_n1, "%u", (unsigned)n1); - stdVectorSU[i] = std::pair< std::string, uint32_t>( std::string(str_n1), n2); - eaVectorSU[i] = eastl::pair(eastl::string(str_n1), n2); - } + stdVectorSU[i] = std::pair< std::string, uint32_t>( std::string(str_n1), n2); + eaVectorSU[i] = eastl::pair(eastl::string(str_n1), n2); + } - for(int i = 0; i < 2; i++) - { - StdMapUint32TO stdMapUint32TO; - EaMapUint32TO eaMapUint32TO; + for(int i = 0; i < 2; i++) + { + StdMapUint32TO stdMapUint32TO; + EaMapUint32TO eaMapUint32TO; - StdMapStrUint32 stdMapStrUint32; - EaMapStrUint32 eaMapStrUint32; + StdMapStrUint32 stdMapStrUint32; + EaMapStrUint32 eaMapStrUint32; - /////////////////////////////// - // Test insert(const value_type&) - /////////////////////////////// + /////////////////////////////// + // Test insert(const value_type&) + /////////////////////////////// - TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); - TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); + TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); + TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); - if(i == 1) - Benchmark::AddResult("hash_map/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - if(i == 1) - Benchmark::AddResult("hash_map/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test iteration - /////////////////////////////// + /////////////////////////////// + // Test iteration + /////////////////////////////// - TestIteration(stopwatch1, stdMapUint32TO, StdMapUint32TO::value_type(9999999, TestObject(9999999))); - TestIteration(stopwatch2, eaMapUint32TO, EaMapUint32TO::value_type(9999999, TestObject(9999999))); + TestIteration(stopwatch1, stdMapUint32TO, StdMapUint32TO::value_type(9999999, TestObject(9999999))); + TestIteration(stopwatch2, eaMapUint32TO, EaMapUint32TO::value_type(9999999, TestObject(9999999))); - if(i == 1) - Benchmark::AddResult("hash_map/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestIteration(stopwatch1, stdMapStrUint32, StdMapStrUint32::value_type( std::string("9999999"), 9999999)); - TestIteration(stopwatch2, eaMapStrUint32, EaMapStrUint32::value_type(eastl::string("9999999"), 9999999)); + TestIteration(stopwatch1, stdMapStrUint32, StdMapStrUint32::value_type( std::string("9999999"), 9999999)); + TestIteration(stopwatch2, eaMapStrUint32, EaMapStrUint32::value_type(eastl::string("9999999"), 9999999)); - if(i == 1) - Benchmark::AddResult("hash_map/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test operator[] - /////////////////////////////// + /////////////////////////////// + // Test operator[] + /////////////////////////////// - TestBracket(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); - TestBracket(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); + TestBracket(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); + TestBracket(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); - if(i == 1) - Benchmark::AddResult("hash_map/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestBracket(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestBracket(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + TestBracket(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestBracket(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - if(i == 1) - Benchmark::AddResult("hash_map/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test find - /////////////////////////////// + /////////////////////////////// + // Test find + /////////////////////////////// - TestFind(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); - TestFind(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); + TestFind(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); + TestFind(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); - if(i == 1) - Benchmark::AddResult("hash_map/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestFind(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestFind(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + TestFind(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestFind(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - if(i == 1) - Benchmark::AddResult("hash_map/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test find_as - /////////////////////////////// + /////////////////////////////// + // Test find_as + /////////////////////////////// - TestFindAsStd(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestFindAsEa(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + TestFindAsStd(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestFindAsEa(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - if(i == 1) - Benchmark::AddResult("hash_map/find_as/char*", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/find_as/char*", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test count - /////////////////////////////// + /////////////////////////////// + // Test count + /////////////////////////////// - TestCount(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); - TestCount(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); + TestCount(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); + TestCount(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); - if(i == 1) - Benchmark::AddResult("hash_map/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestCount(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestCount(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + TestCount(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestCount(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - if(i == 1) - Benchmark::AddResult("hash_map/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test erase(const key_type& key) - /////////////////////////////// + /////////////////////////////// + // Test erase(const key_type& key) + /////////////////////////////// - TestEraseValue(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + (stdVectorUT.size() / 2)); - TestEraseValue(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + (eaVectorUT.size() / 2)); + TestEraseValue(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + (stdVectorUT.size() / 2)); + TestEraseValue(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + (eaVectorUT.size() / 2)); - if(i == 1) - Benchmark::AddResult("hash_map/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestEraseValue(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + (stdVectorSU.size() / 2)); - TestEraseValue(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + (eaVectorSU.size() / 2)); + TestEraseValue(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + (stdVectorSU.size() / 2)); + TestEraseValue(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + (eaVectorSU.size() / 2)); - if(i == 1) - Benchmark::AddResult("hash_map/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test erase(iterator position) - /////////////////////////////// + /////////////////////////////// + // Test erase(iterator position) + /////////////////////////////// - TestErasePosition(stopwatch1, stdMapUint32TO); - TestErasePosition(stopwatch2, eaMapUint32TO); + TestErasePosition(stopwatch1, stdMapUint32TO); + TestErasePosition(stopwatch2, eaMapUint32TO); - if(i == 1) - Benchmark::AddResult("hash_map/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestErasePosition(stopwatch1, stdMapStrUint32); - TestErasePosition(stopwatch2, eaMapStrUint32); + TestErasePosition(stopwatch1, stdMapStrUint32); + TestErasePosition(stopwatch2, eaMapStrUint32); - if(i == 1) - Benchmark::AddResult("hash_map/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test erase(iterator first, iterator last) - /////////////////////////////// + /////////////////////////////// + // Test erase(iterator first, iterator last) + /////////////////////////////// - TestEraseRange(stopwatch1, stdMapUint32TO); - TestEraseRange(stopwatch2, eaMapUint32TO); + TestEraseRange(stopwatch1, stdMapUint32TO); + TestEraseRange(stopwatch2, eaMapUint32TO); - if(i == 1) - Benchmark::AddResult("hash_map/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestEraseRange(stopwatch1, stdMapStrUint32); - TestEraseRange(stopwatch2, eaMapStrUint32); + TestEraseRange(stopwatch1, stdMapStrUint32); + TestEraseRange(stopwatch2, eaMapStrUint32); - if(i == 1) - Benchmark::AddResult("hash_map/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - /////////////////////////////// - // Test clear() - /////////////////////////////// + /////////////////////////////// + // Test clear() + /////////////////////////////// - // Clear the containers of whatever they happen to have. We want the containers to have full data. - TestClear(stopwatch1, stdMapUint32TO); - TestClear(stopwatch2, eaMapUint32TO); - TestClear(stopwatch1, stdMapStrUint32); - TestClear(stopwatch2, eaMapStrUint32); + // Clear the containers of whatever they happen to have. We want the containers to have full data. + TestClear(stopwatch1, stdMapUint32TO); + TestClear(stopwatch2, eaMapUint32TO); + TestClear(stopwatch1, stdMapStrUint32); + TestClear(stopwatch2, eaMapStrUint32); - // Re-set the containers with full data. - TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); - TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); - TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); - TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); + // Re-set the containers with full data. + TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size()); + TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size()); + TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size()); + TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size()); - // Now clear the data again, this time measuring it. - TestClear(stopwatch1, stdMapUint32TO); - TestClear(stopwatch2, eaMapUint32TO); + // Now clear the data again, this time measuring it. + TestClear(stopwatch1, stdMapUint32TO); + TestClear(stopwatch2, eaMapUint32TO); - if(i == 1) - Benchmark::AddResult("hash_map/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - TestClear(stopwatch1, stdMapStrUint32); - TestClear(stopwatch2, eaMapStrUint32); + TestClear(stopwatch1, stdMapStrUint32); + TestClear(stopwatch2, eaMapStrUint32); - if(i == 1) - Benchmark::AddResult("hash_map/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); + if(i == 1) + Benchmark::AddResult("hash_map/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()); - } } - #else - EASTLTest_Printf("HashMap...Unsupported by the tested std STL.\n"); - #endif + } } diff --git a/benchmark/source/BenchmarkSort.cpp b/benchmark/source/BenchmarkSort.cpp index ef1e6da9..1c984fc0 100644 --- a/benchmark/source/BenchmarkSort.cpp +++ b/benchmark/source/BenchmarkSort.cpp @@ -10,17 +10,12 @@ #include "EASTLBenchmark.h" #include "EASTLTest.h" -#ifdef _MSC_VER - #pragma warning(push, 0) - #pragma warning(disable: 4350) -#endif +EA_DISABLE_ALL_VC_WARNINGS() #include #include #include #include -#ifdef _MSC_VER - #pragma warning(pop) -#endif +EA_RESTORE_ALL_VC_WARNINGS() using namespace EA; @@ -1168,6 +1163,8 @@ static int CompareSmallInputSortPerformanceHelper(eastl::vector &a stopwatch.Stop(); break; + case sf_qsort: + case sf_radix_sort: case sf_count: default: EATEST_VERIFY_F(false, "Missing case statement for sort function %s.", GetSortFunctionName(sortFunction)); diff --git a/include/EASTL/internal/config.h b/include/EASTL/internal/config.h index 3538bf14..3175c6fe 100644 --- a/include/EASTL/internal/config.h +++ b/include/EASTL/internal/config.h @@ -89,8 +89,8 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef EASTL_VERSION - #define EASTL_VERSION "3.12.07" - #define EASTL_VERSION_N 31207 + #define EASTL_VERSION "3.12.08" + #define EASTL_VERSION_N 31208 #endif diff --git a/include/EASTL/internal/function_detail.h b/include/EASTL/internal/function_detail.h index d8d6c1e0..0da6ae04 100644 --- a/include/EASTL/internal/function_detail.h +++ b/include/EASTL/internal/function_detail.h @@ -407,6 +407,7 @@ namespace eastl template function_detail& operator=(Functor&& functor) { + Destroy(); CreateForwardFunctor(eastl::forward(functor)); return *this; } @@ -414,6 +415,7 @@ namespace eastl template function_detail& operator=(eastl::reference_wrapper f) EA_NOEXCEPT { + Destroy(); CreateForwardFunctor(f); return *this; } diff --git a/include/EASTL/list.h b/include/EASTL/list.h index cbd558d2..066b5349 100644 --- a/include/EASTL/list.h +++ b/include/EASTL/list.h @@ -384,10 +384,10 @@ namespace eastl iterator insert(const_iterator position, const value_type& value); iterator insert(const_iterator position, value_type&& x); iterator insert(const_iterator position, std::initializer_list ilist); - void insert(const_iterator position, size_type n, const value_type& value); // TODO(rparolin): return iterator C++11 support + iterator insert(const_iterator position, size_type n, const value_type& value); template - void insert(const_iterator position, InputIterator first, InputIterator last); // TODO(rparolin): return iterator C++11 support + iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); @@ -1374,18 +1374,25 @@ namespace eastl } template - inline void list::insert(const_iterator position, size_type n, const value_type& value) + inline typename list::iterator + list::insert(const_iterator position, size_type n, const value_type& value) { - // To do: Get rid of DoInsertValues and put its implementation directly here. + iterator itPrev(position.mpNode); + --itPrev; DoInsertValues((ListNodeBase*)position.mpNode, n, value); + return ++itPrev; // Inserts in front of position, returns iterator to new elements. } template template - inline void list::insert(const_iterator position, InputIterator first, InputIterator last) + inline typename list::iterator + list::insert(const_iterator position, InputIterator first, InputIterator last) { + iterator itPrev(position.mpNode); + --itPrev; DoInsert((ListNodeBase*)position.mpNode, first, last, is_integral()); + return ++itPrev; // Inserts in front of position, returns iterator to new elements. } diff --git a/include/EASTL/scoped_array.h b/include/EASTL/scoped_array.h index 5b38d9a3..c955dbaf 100644 --- a/include/EASTL/scoped_array.h +++ b/include/EASTL/scoped_array.h @@ -126,7 +126,7 @@ namespace eastl /// Example usage: /// scoped_array ptr(new int[6]); /// int x = ptr[2]; - T& operator[](ptrdiff_t i) const + typename add_lvalue_reference::type operator[](ptrdiff_t i) const { // assert(mpArray && (i >= 0)); return mpArray[i]; diff --git a/include/EASTL/scoped_ptr.h b/include/EASTL/scoped_ptr.h index ac43fd3e..3ba01daa 100644 --- a/include/EASTL/scoped_ptr.h +++ b/include/EASTL/scoped_ptr.h @@ -145,7 +145,7 @@ namespace eastl /// Example usage: /// scoped_ptr ptr(new int(3)); /// int x = *ptr; - T& operator*() const + typename add_lvalue_reference::type operator*() const { // assert(mpValue); return *mpValue; diff --git a/test/packages/EABase/include/Common/EABase/config/eaplatform.h b/test/packages/EABase/include/Common/EABase/config/eaplatform.h index c91c86b2..cadd8111 100644 --- a/test/packages/EABase/include/Common/EABase/config/eaplatform.h +++ b/test/packages/EABase/include/Common/EABase/config/eaplatform.h @@ -340,7 +340,7 @@ #define EA_PLATFORM_DESCRIPTION "OSX on ARM64" #elif defined(__POWERPC64__) || defined(__powerpc64__) #define EA_PROCESSOR_POWERPC 1 - #define CS_UNDEFINED_STRING 1 + #define EA_PROCESSOR_POWERPC_64 1 #define EA_SYSTEM_BIG_ENDIAN 1 #define EA_PLATFORM_DESCRIPTION "OSX on PowerPC 64" #elif defined(__POWERPC__) || defined(__powerpc__) @@ -393,7 +393,7 @@ #define EA_PLATFORM_DESCRIPTION "Linux on x64" #elif defined(__powerpc64__) #define EA_PROCESSOR_POWERPC 1 - #define CS_UNDEFINED_STRING 1 + #define EA_PROCESSOR_POWERPC_64 1 #define EA_SYSTEM_BIG_ENDIAN 1 #define EA_PLATFORM_DESCRIPTION "Linux on PowerPC 64" #elif defined(__powerpc__) @@ -427,7 +427,7 @@ #define EA_PLATFORM_DESCRIPTION "BSD on x64" #elif defined(__powerpc64__) #define EA_PROCESSOR_POWERPC 1 - #define CS_UNDEFINED_STRING 1 + #define EA_PROCESSOR_POWERPC_64 1 #define EA_SYSTEM_BIG_ENDIAN 1 #define EA_PLATFORM_DESCRIPTION "BSD on PowerPC 64" #elif defined(__powerpc__) diff --git a/test/source/TestFunctional.cpp b/test/source/TestFunctional.cpp index a9af2be6..e582a11a 100644 --- a/test/source/TestFunctional.cpp +++ b/test/source/TestFunctional.cpp @@ -15,7 +15,7 @@ EA_DISABLE_ALL_VC_WARNINGS() #include -EA_RESTORE_ALL_VC_WARNINGS(); +EA_RESTORE_ALL_VC_WARNINGS() namespace { @@ -795,7 +795,6 @@ int TestFunctional() EATEST_VERIFY(fn0() == 1 && fn1() == 1); } - #if !EASTL_NO_RVALUE_REFERENCES { eastl::function fn0 = ReturnZero; eastl::function fn1 = ReturnOne; @@ -804,7 +803,6 @@ int TestFunctional() fn0 = eastl::move(fn1); EATEST_VERIFY(fn0() == 1 && fn1 == nullptr); } - #endif { eastl::function f1(nullptr); @@ -895,6 +893,33 @@ int TestFunctional() EATEST_VERIFY(fn() == 7); EATEST_VERIFY(fn() == 8); } + + // user regression for memory leak when re-assigning an eastl::function which already holds a large closure. + { + static int sCtorCount = 0; + static int sDtorCount = 0; + + { + struct local + { + local() { sCtorCount++; } + local(const local&) { sCtorCount++; } + local(local&&) { sCtorCount++; } + ~local() { sDtorCount++; } + + void operator=(const local&) = delete; // suppress msvc warning + } l; + + eastl::function f; + + f = [l]() { return false; }; + + // ensure closure resources are cleaned up when assigning to a non-null eastl::function. + f = [l]() { return true; }; + } + + EATEST_VERIFY(sCtorCount == sDtorCount); + } } // Checking _MSC_EXTENSIONS is required because the Microsoft calling convention classifiers are only available when diff --git a/test/source/TestList.cpp b/test/source/TestList.cpp index 24c8dc66..712e2fd4 100644 --- a/test/source/TestList.cpp +++ b/test/source/TestList.cpp @@ -618,8 +618,10 @@ int TestList() auto insert_pos = a.begin(); eastl::advance(insert_pos, 5); - a.insert(insert_pos, 4, 42); + auto result = a.insert(insert_pos, 4, 42); VERIFY(a == ref); + VERIFY(*result == 42); + VERIFY(*(--result) == 4); } // void insert(const_iterator position, InputIterator first, InputIterator last); @@ -631,8 +633,10 @@ int TestList() auto insert_pos = a.begin(); eastl::advance(insert_pos, 5); - a.insert(insert_pos, to_insert.begin(), to_insert.end()); + auto result = a.insert(insert_pos, to_insert.begin(), to_insert.end()); VERIFY(a == ref); + VERIFY(*result == 42); + VERIFY(*(--result) == 4); } // iterator insert(const_iterator position, std::initializer_list ilist); diff --git a/test/source/TestOptional.cpp b/test/source/TestOptional.cpp index c5074650..2c864f80 100644 --- a/test/source/TestOptional.cpp +++ b/test/source/TestOptional.cpp @@ -539,10 +539,12 @@ int TestOptional() } { // user regression + EA_DISABLE_VC_WARNING(4625 4626) // copy/assignment operator constructor was implicitly defined as deleted struct local { eastl::unique_ptr ptr; }; + EA_RESTORE_VC_WARNING() eastl::optional o1 = local{eastl::make_unique(42)}; eastl::optional o2; diff --git a/test/source/TestSmartPtr.cpp b/test/source/TestSmartPtr.cpp index 182044cf..cf36c7ac 100644 --- a/test/source/TestSmartPtr.cpp +++ b/test/source/TestSmartPtr.cpp @@ -823,6 +823,11 @@ static int Test_scoped_ptr() delete pA; } + { + scoped_ptr ptr(new int); + (void)ptr; + } + EATEST_VERIFY(A::mCount == 0); return nErrorCount; @@ -880,6 +885,11 @@ static int Test_scoped_array() delete[] pArray; } + { + scoped_array ptr(new int[6]); + (void)ptr; + } + EATEST_VERIFY(A::mCount == 0); return nErrorCount;