From 7ef3a6a2aaf45613d8aa5056a22838a0ce55cc76 Mon Sep 17 00:00:00 2001 From: Rob Parolin Date: Wed, 25 May 2016 16:30:28 -0700 Subject: [PATCH] 3.01.01 release --- include/EASTL/allocator_malloc.h | 4 +- include/EASTL/fixed_hash_map.h | 70 +++++++++++---- include/EASTL/fixed_hash_set.h | 67 ++++++++++---- include/EASTL/internal/config.h | 4 +- include/EASTL/internal/fixed_pool.h | 17 +++- include/EASTL/internal/type_compound.h | 36 ++------ include/EASTL/internal/type_fundamental.h | 17 ++++ include/EASTL/internal/type_pod.h | 8 +- include/EASTL/iterator.h | 52 +++++++++++ include/EASTL/set.h | 4 +- include/EASTL/type_traits.h | 22 +++-- .../include/Common/EABase/config/eacompiler.h | 10 +++ .../EABase/include/Common/EABase/version.h | 4 +- test/source/EASTLTest.h | 1 + test/source/TestCppCXTypeTraits.cpp | 37 ++++++++ test/source/TestFixedHash.cpp | 21 +++++ test/source/TestIterator.cpp | 46 ++++++++++ test/source/TestTypeTraits.cpp | 6 +- test/source/main.cpp | 89 ++++++++++--------- 19 files changed, 380 insertions(+), 135 deletions(-) create mode 100644 test/source/TestCppCXTypeTraits.cpp diff --git a/include/EASTL/allocator_malloc.h b/include/EASTL/allocator_malloc.h index aa1c85e2..fe59b706 100644 --- a/include/EASTL/allocator_malloc.h +++ b/include/EASTL/allocator_malloc.h @@ -88,10 +88,10 @@ namespace eastl void* allocate(size_t n, size_t alignment, size_t alignmentOffset, int /*flags*/ = 0) { #if EASTL_ALIGNED_MALLOC_AVAILABLE - if((alignmentOffset % alignment) != 0) // We check for (offset % alignmnent == 0) instead of (offset == 0) because any block which is aligned on e.g. 64 also is aligned at an offset of 64 by definition. + if((alignmentOffset % alignment) == 0) // We check for (offset % alignmnent == 0) instead of (offset == 0) because any block which is aligned on e.g. 64 also is aligned at an offset of 64 by definition. return memalign(alignment, n); // memalign is more consistently available than posix_memalign. #else - if((alignment <= EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT) && ((alignmentOffset % alignment) != 0)) + if((alignment <= EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT) && ((alignmentOffset % alignment) == 0)) return malloc(n); #endif return NULL; diff --git a/include/EASTL/fixed_hash_map.h b/include/EASTL/fixed_hash_map.h index 03de9897..3518bd8b 100644 --- a/include/EASTL/fixed_hash_map.h +++ b/include/EASTL/fixed_hash_map.h @@ -15,12 +15,13 @@ #include #include +EA_DISABLE_VC_WARNING(4127) // Conditional expression is constant + #if defined(EA_PRAGMA_ONCE_SUPPORTED) #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. #endif - namespace eastl { /// EASTL_FIXED_HASH_MAP_DEFAULT_NAME @@ -255,7 +256,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME); @@ -273,7 +276,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME); @@ -292,7 +297,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME); @@ -312,7 +319,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME); @@ -336,7 +345,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -358,7 +369,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -379,7 +392,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -394,7 +409,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MAP_DEFAULT_NAME); @@ -522,7 +539,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME); @@ -540,7 +559,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME); @@ -559,7 +580,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME); @@ -579,7 +602,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME); @@ -603,7 +628,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -625,7 +652,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -646,7 +675,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -661,7 +692,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTIMAP_DEFAULT_NAME); @@ -777,8 +810,7 @@ namespace eastl } // namespace eastl - - +EA_RESTORE_VC_WARNING() #endif // Header include guard diff --git a/include/EASTL/fixed_hash_set.h b/include/EASTL/fixed_hash_set.h index 155bf1de..c4aba619 100644 --- a/include/EASTL/fixed_hash_set.h +++ b/include/EASTL/fixed_hash_set.h @@ -15,6 +15,8 @@ #include #include +EA_DISABLE_VC_WARNING(4127) // Conditional expression is constant + #if defined(EA_PRAGMA_ONCE_SUPPORTED) #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result. #endif @@ -251,7 +253,9 @@ namespace eastl Hash(), Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME); @@ -269,7 +273,9 @@ namespace eastl hashFunction, predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME); @@ -288,7 +294,9 @@ namespace eastl hashFunction, predicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME); @@ -308,7 +316,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME); @@ -332,7 +342,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -353,7 +365,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -373,7 +387,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -388,7 +404,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_SET_DEFAULT_NAME); @@ -523,7 +541,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME); @@ -541,7 +561,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME); @@ -560,7 +582,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME); @@ -580,7 +604,9 @@ namespace eastl predicate, fixed_allocator_type(NULL, mBucketBuffer)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME); @@ -604,7 +630,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -625,7 +653,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -645,7 +675,9 @@ namespace eastl #endif EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. mAllocator.reset(mNodeBuffer); base_type::insert(x.begin(), x.end()); @@ -660,7 +692,9 @@ namespace eastl Predicate(), fixed_allocator_type(NULL, mBucketBuffer, overflowAllocator)) { EASTL_CT_ASSERT((nodeCount >= 1) && (bucketCount >= 2)); - base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. + + if(!bEnableOverflow) + base_type::set_max_load_factor(10000.f); // Set it so that we will never resize. #if EASTL_NAME_ENABLED mAllocator.set_name(EASTL_FIXED_HASH_MULTISET_DEFAULT_NAME); @@ -776,6 +810,7 @@ namespace eastl } // namespace eastl +EA_RESTORE_VC_WARNING() #endif // Header include guard diff --git a/include/EASTL/internal/config.h b/include/EASTL/internal/config.h index ee32ad48..29e0e887 100644 --- a/include/EASTL/internal/config.h +++ b/include/EASTL/internal/config.h @@ -105,8 +105,8 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef EASTL_VERSION - #define EASTL_VERSION "3.01.00" - #define EASTL_VERSION_N 30100 + #define EASTL_VERSION "3.01.01" + #define EASTL_VERSION_N 30101 #endif diff --git a/include/EASTL/internal/fixed_pool.h b/include/EASTL/internal/fixed_pool.h index 3947ca9b..14674c36 100644 --- a/include/EASTL/internal/fixed_pool.h +++ b/include/EASTL/internal/fixed_pool.h @@ -1020,12 +1020,17 @@ namespace eastl { // We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes. EASTL_CT_ASSERT(kAllocFlagBuckets == 0x00400000); // Currently we expect this to be so, because the hashtable has a copy of this enum. + if((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets... { - EASTL_ASSERT(n == kNodeSize); (void)n; // Make unused var warning go away. + EASTL_ASSERT(n == kNodeSize); EA_UNUSED(n); return mPool.allocate(); } + // If bucket size no longer fits within local buffer... + if ((flags & kAllocFlagBuckets) == kAllocFlagBuckets && (n > kBucketsSize)) + return get_overflow_allocator().allocate(n); + EASTL_ASSERT(n <= kBucketsSize); return mpBucketBuffer; } @@ -1036,11 +1041,14 @@ namespace eastl // We expect that the caller uses kAllocFlagBuckets when it wants us to allocate buckets instead of nodes. if ((flags & kAllocFlagBuckets) == 0) // If we are allocating nodes and (probably) not buckets... { - EASTL_ASSERT(n == kNodeSize); (void)n; // Make unused var warning go away. + EASTL_ASSERT(n == kNodeSize); EA_UNUSED(n); return mPool.allocate(alignment, offset); } - // To consider: allow for bucket allocations to overflow. + // If bucket size no longer fits within local buffer... + if ((flags & kAllocFlagBuckets) == kAllocFlagBuckets && (n > kBucketsSize)) + return get_overflow_allocator().allocate(n, alignment, offset); + EASTL_ASSERT(n <= kBucketsSize); return mpBucketBuffer; } @@ -1197,6 +1205,7 @@ namespace eastl return mPool.allocate(); } + // Don't allow hashtable buckets to overflow in this case. EASTL_ASSERT(n <= kBucketsSize); return mpBucketBuffer; } @@ -1211,7 +1220,7 @@ namespace eastl return mPool.allocate(alignment, offset); } - // To consider: allow for bucket allocations to overflow. + // Don't allow hashtable buckets to overflow in this case. EASTL_ASSERT(n <= kBucketsSize); return mpBucketBuffer; } diff --git a/include/EASTL/internal/type_compound.h b/include/EASTL/internal/type_compound.h index a9295411..bf8b3461 100644 --- a/include/EASTL/internal/type_compound.h +++ b/include/EASTL/internal/type_compound.h @@ -32,38 +32,14 @@ namespace eastl #define EASTL_TYPE_TRAIT_is_array_CONFORMANCE 1 // is_array is conforming; doesn't make mistakes. - #if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_MSC_VER_) && _MSC_VER < 1500) // If the compiler is crippled... - - template - T (*is_array_tester1(empty))(empty); - char is_array_tester1(...); // May need to use __cdecl under VC++. - - template - no_type is_array_tester2(T(*)(empty)); - yes_type is_array_tester2(...); // May need to use __cdecl under VC++. - - template - struct is_array_helper { - static empty emptyInstance; - }; - - template - struct is_array : public integral_constant::emptyInstance))) == 1 - >{}; - - #else + template + struct is_array : public eastl::false_type {}; - template - struct is_array : public eastl::false_type {}; - - template - struct is_array : public eastl::true_type {}; - - template - struct is_array : public eastl::true_type {}; + template + struct is_array : public eastl::true_type {}; - #endif + template + struct is_array : public eastl::true_type {}; /////////////////////////////////////////////////////////////////////// diff --git a/include/EASTL/internal/type_fundamental.h b/include/EASTL/internal/type_fundamental.h index 3c1fbbfd..2473dbd8 100644 --- a/include/EASTL/internal/type_fundamental.h +++ b/include/EASTL/internal/type_fundamental.h @@ -215,6 +215,23 @@ namespace eastl >{}; + /////////////////////////////////////////////////////////////////////// + // is_hat_type + // + // is_hat_type::value == true if and only if: + // underlying type is a C++/CX '^' type such as: Foo^ + // meaning the type is heap allocated and ref-counted + /////////////////////////////////////////////////////////////////////// + + template struct is_hat_type_helper : public false_type {}; + + #if (EABASE_VERSION_N > 20607 && defined(EA_COMPILER_WINRTCX_ENABLED)) || defined(__cplusplus_winrt) + template struct is_hat_type_helper : public true_type{}; + #endif + + template + struct is_hat_type : public eastl::is_hat_type_helper {}; + } // namespace eastl diff --git a/include/EASTL/internal/type_pod.h b/include/EASTL/internal/type_pod.h index 5de75466..d9866b20 100644 --- a/include/EASTL/internal/type_pod.h +++ b/include/EASTL/internal/type_pod.h @@ -86,7 +86,7 @@ namespace eastl EA_DISABLE_VC_WARNING(4647) template // We check for has_trivial_constructor only because the VC++ is_pod does. Is it due to some compiler bug? - struct is_pod : public eastl::integral_constant::value || eastl::is_scalar::value>{}; + struct is_pod : public eastl::integral_constant::value) || eastl::is_void::value || eastl::is_scalar::value>{}; EA_RESTORE_VC_WARNING() #elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_GNUC) || (defined(EA_COMPILER_CLANG) && EA_COMPILER_HAS_FEATURE(is_pod))) @@ -176,7 +176,7 @@ namespace eastl #define EASTL_TYPE_TRAIT_has_trivial_constructor_CONFORMANCE 1 // has_trivial_constructor is conforming. template - struct has_trivial_constructor : public eastl::integral_constant::value>{}; + struct has_trivial_constructor : public eastl::integral_constant::value) && !eastl::is_hat_type::value>{}; #elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(_MSC_VER) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) #define EASTL_TYPE_TRAIT_has_trivial_constructor_CONFORMANCE 1 // has_trivial_constructor is conforming. @@ -236,7 +236,7 @@ namespace eastl #define EASTL_TYPE_TRAIT_has_trivial_copy_CONFORMANCE 1 // has_trivial_copy is conforming. template - struct has_trivial_copy : public eastl::integral_constant::value) && !eastl::is_volatile::value>{}; + struct has_trivial_copy : public eastl::integral_constant::value) && !eastl::is_volatile::value && !eastl::is_hat_type::value>{}; #elif EASTL_COMPILER_INTRINSIC_TYPE_TRAITS_AVAILABLE && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) #define EASTL_TYPE_TRAIT_has_trivial_copy_CONFORMANCE 1 // has_trivial_copy is conforming. @@ -1759,7 +1759,7 @@ namespace eastl template struct is_trivially_destructible // Can't use just __has_trivial_destructor(T) because some compilers give it slightly different meaning, and are just plain broken, such as VC++'s __has_trivial_destructor, which says false for fundamental types. - : public integral_constant::value && (__has_trivial_destructor(T) || eastl::is_scalar::type>::value)> {}; + : public integral_constant::value && ((__has_trivial_destructor(T) && !eastl::is_hat_type::value)|| eastl::is_scalar::type>::value)> {}; #else #define EASTL_TYPE_TRAIT_is_trivially_destructible_CONFORMANCE 0 diff --git a/include/EASTL/iterator.h b/include/EASTL/iterator.h index 37b94707..f660b69b 100644 --- a/include/EASTL/iterator.h +++ b/include/EASTL/iterator.h @@ -1013,6 +1013,58 @@ namespace eastl return it; } + + // eastl::data + // + // http://en.cppreference.com/w/cpp/iterator/data + // + template + EA_CONSTEXPR auto data(Container& c) -> decltype(c.data()) + { return c.data(); } + + template + EA_CONSTEXPR auto data(const Container& c) -> decltype(c.data()) + { return c.data(); } + + template + EA_CONSTEXPR T* data(T(&array)[N]) EA_NOEXCEPT + { return array; } + + template + EA_CONSTEXPR const E* data(std::initializer_list il) EA_NOEXCEPT + { return il.begin(); } + + + // eastl::size + // + // http://en.cppreference.com/w/cpp/iterator/size + // + template + EA_CONSTEXPR auto size(const C& c) -> decltype(c.size()) + { return c.size(); } + + template + EA_CONSTEXPR std::size_t size(const T (&)[N]) EA_NOEXCEPT + { return N; } + + + // eastl::empty + // + // http://en.cppreference.com/w/cpp/iterator/empty + // + template + EA_CONSTEXPR auto empty(const Container& c) -> decltype(c.empty()) + { return c.empty(); } + + template + EA_CONSTEXPR bool empty(const T (&)[N]) EA_NOEXCEPT + { return false; } + + template + EA_CONSTEXPR bool empty(std::initializer_list il) EA_NOEXCEPT + { return il.size() == 0; } + + // eastl::begin / eastl::end // http://en.cppreference.com/w/cpp/iterator/begin // diff --git a/include/EASTL/set.h b/include/EASTL/set.h index bfba90f4..f618e51b 100644 --- a/include/EASTL/set.h +++ b/include/EASTL/set.h @@ -108,8 +108,8 @@ namespace eastl set(const Compare& compare, const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR); set(const this_type& x); #if EASTL_MOVE_SEMANTICS_ENABLED - set(this_type&& x); - set(this_type&& x, const allocator_type& allocator); + set(this_type&& x); + set(this_type&& x, const allocator_type& allocator); #endif set(std::initializer_list ilist, const Compare& compare = Compare(), const allocator_type& allocator = EASTL_SET_DEFAULT_ALLOCATOR); diff --git a/include/EASTL/type_traits.h b/include/EASTL/type_traits.h index feda39ab..db6d2073 100644 --- a/include/EASTL/type_traits.h +++ b/include/EASTL/type_traits.h @@ -276,6 +276,19 @@ namespace eastl typedef integral_constant false_type; + /////////////////////////////////////////////////////////////////////// + // bool_constant + // + // This is a convenience helper for the often used integral_constant. + // + #if defined(EA_COMPILER_NO_TEMPLATE_ALIASES) + template + struct bool_constant : public integral_constant {}; + #else + template + using bool_constant = integral_constant; + #endif + /////////////////////////////////////////////////////////////////////// // yes_type / no_type @@ -286,12 +299,6 @@ namespace eastl struct no_type { char padding[8]; }; // sizeof(no_type) != 1 - /////////////////////////////////////////////////////////////////////// - // empty - // - template - struct empty{ }; - /////////////////////////////////////////////////////////////////////// // unused @@ -299,7 +306,7 @@ namespace eastl // Used internally to denote a special template argument that means // it's an unused argument. // - struct unused{ }; + struct unused { }; /////////////////////////////////////////////////////////////////////// @@ -307,7 +314,6 @@ namespace eastl // // Used as a type which constructs from anything. // - #if defined(EA_COMPILER_NO_VARIADIC_TEMPLATES) struct argument_sink{ argument_sink(...){} }; #else diff --git a/test/packages/EABase/include/Common/EABase/config/eacompiler.h b/test/packages/EABase/include/Common/EABase/config/eacompiler.h index 6e9142c0..aadaf59f 100644 --- a/test/packages/EABase/include/Common/EABase/config/eacompiler.h +++ b/test/packages/EABase/include/Common/EABase/config/eacompiler.h @@ -221,6 +221,16 @@ #endif #endif + // EA_COMPILER_WINRTCX_ENABLED + // + // Defined as 1 if the compiler has its available C++/CX support enabled, else undefined. + // This specifically means the corresponding compilation unit has been built with Windows Runtime + // Components enabled, usually via the '-ZW' compiler flags being used. This option allows for using + // ref counted hat-type '^' objects and other C++/CX specific keywords like "ref new" + #if !defined(EA_COMPILER_WINRTCX_ENABLED) && defined(__cplusplus_winrt) + #define EA_COMPILER_WINRTCX_ENABLED 1 + #endif + // EA_COMPILER_CPP11_ENABLED // diff --git a/test/packages/EABase/include/Common/EABase/version.h b/test/packages/EABase/include/Common/EABase/version.h index 3914a252..713a8246 100644 --- a/test/packages/EABase/include/Common/EABase/version.h +++ b/test/packages/EABase/include/Common/EABase/version.h @@ -29,8 +29,8 @@ /////////////////////////////////////////////////////////////////////////////// #ifndef EABASE_VERSION - #define EABASE_VERSION "2.06.07" - #define EABASE_VERSION_N 20607 + #define EABASE_VERSION "2.07.00" + #define EABASE_VERSION_N 20700 #endif #endif diff --git a/test/source/EASTLTest.h b/test/source/EASTLTest.h index 83f3fb0c..fb16ae76 100644 --- a/test/source/EASTLTest.h +++ b/test/source/EASTLTest.h @@ -40,6 +40,7 @@ int TestRandom(); int TestNumericLimits(); int TestBitset(); int TestTypeTraits(); +int TestCppCXTypeTraits(); int TestSmartPtr(); int TestList(); int TestListMap(); diff --git a/test/source/TestCppCXTypeTraits.cpp b/test/source/TestCppCXTypeTraits.cpp new file mode 100644 index 00000000..9a17cddb --- /dev/null +++ b/test/source/TestCppCXTypeTraits.cpp @@ -0,0 +1,37 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) Electronic Arts Inc. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + + +#include "EASTLTest.h" +#include + +using namespace eastl; + +#if defined(__cplusplus_winrt) + ref class Foo + { + + }; +#endif + +int TestCppCXTypeTraits() +{ + EASTLTest_Printf("TestCppCXTypeTraits\n"); + + int nErrorCount = 0; + + // We can only build this code if C++/CX is enabled +#if defined(__cplusplus_winrt) + { + Foo^ foo = ref new Foo(); + static_assert(eastl::is_pod::value == false, "Ref types are not POD"); + static_assert(eastl::is_trivially_destructible::value == false, "Ref types cannot be trivially destructible"); + static_assert(eastl::is_trivially_constructible::value == false, "Ref types cannot be trivially constructible"); + static_assert(eastl::is_trivially_copy_constructible::value == false, "Ref types cannot be trivially copyable"); + static_assert(eastl::is_trivially_copy_assignable::value == false, "Ref types cannot be trivially copyable"); + } +#endif + + return nErrorCount; +} diff --git a/test/source/TestFixedHash.cpp b/test/source/TestFixedHash.cpp index bdf0aa52..531a6de4 100644 --- a/test/source/TestFixedHash.cpp +++ b/test/source/TestFixedHash.cpp @@ -8,6 +8,7 @@ #include "TestSet.h" #include #include +#include #include @@ -211,6 +212,26 @@ int TestFixedHash() EASTLAllocatorType a = fixedHashMap.get_allocator().get_overflow_allocator(); fixedHashMap.get_allocator().set_overflow_allocator(a); } + + { + // Test fixed_hash_map *with* overflow and ensure the underlying hashtable rehashes. + typedef eastl::fixed_hash_map, eastl::equal_to, false, MallocAllocator> FixedHashMap; + + FixedHashMap fixedHashMap; + auto old_bucket_count = fixedHashMap.bucket_count(); + auto old_load_factor = fixedHashMap.load_factor(); + + for (int i = 0; i < 1000; i++) + fixedHashMap.insert(i); + + auto new_bucket_count = fixedHashMap.bucket_count(); + auto new_load_factor = fixedHashMap.load_factor(); + + VERIFY(new_bucket_count != old_bucket_count); + VERIFY(new_bucket_count > old_bucket_count); + VERIFY(new_load_factor != old_load_factor); + VERIFY(fixedHashMap.get_overflow_allocator().mAllocCountAll != 0); + } { // Test version with overflow and alignment requirements. diff --git a/test/source/TestIterator.cpp b/test/source/TestIterator.cpp index 7635de40..b7cb8ead 100644 --- a/test/source/TestIterator.cpp +++ b/test/source/TestIterator.cpp @@ -233,6 +233,52 @@ int TestIterator() #endif } + // eastl::data + { + eastl::array intArray; + int* pIntArrayData = eastl::data(intArray); + EATEST_VERIFY(pIntArrayData == intArray.data()); + + eastl::vector intVector; + int* pIntVectorData = eastl::data(intVector); + EATEST_VERIFY(pIntVectorData == intVector.data()); + + int intCArray[34]; + int* pIntCArray = eastl::data(intCArray); + EATEST_VERIFY(pIntCArray == intCArray); + + std::initializer_list intInitList; + const int* pIntInitList = eastl::data(intInitList); + EATEST_VERIFY(pIntInitList == intInitList.begin()); + } + + // eastl::size + { + eastl::vector intVector; + intVector.push_back(); + intVector.push_back(); + intVector.push_back(); + EATEST_VERIFY(eastl::size(intVector) == 3); + + int intCArray[34]; + EATEST_VERIFY(eastl::size(intCArray) == 34); + } + + // eastl::empty + { + eastl::vector intVector; + EATEST_VERIFY(eastl::empty(intVector)); + intVector.push_back(); + EATEST_VERIFY(!eastl::empty(intVector)); + + std::initializer_list intInitListEmpty; + EATEST_VERIFY(eastl::empty(intInitListEmpty)); + + #if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) + EATEST_VERIFY(!eastl::empty({1, 2, 3, 4, 5, 6})); + #endif + } + // Range-based for loops #if !defined(EA_COMPILER_NO_RANGE_BASED_FOR_LOOP) { diff --git a/test/source/TestTypeTraits.cpp b/test/source/TestTypeTraits.cpp index 2f69f9e9..9b01b0fa 100644 --- a/test/source/TestTypeTraits.cpp +++ b/test/source/TestTypeTraits.cpp @@ -473,9 +473,11 @@ int TestTypeTraits() static_assert(sizeof(conditional::type) == sizeof(int8_t), "conditional failure"); static_assert(sizeof(conditional::type) == sizeof(int16_t), "conditional failure"); + // bool_constant + static_assert(bool_constant::value>::value == true, "bool_constant failure"); + static_assert(bool_constant::value>::value == false, "bool_constant failure"); + static_assert(is_same::type, integral_constant::type>::value, "bool_constant failure"); - // empty - static_assert(sizeof(empty) > 0, "empty failure"); // identity diff --git a/test/source/main.cpp b/test/source/main.cpp index 4d811443..8316b0f3 100644 --- a/test/source/main.cpp +++ b/test/source/main.cpp @@ -13,7 +13,7 @@ #include #include #include - #include +#include #include "EAMain/EAEntryPointMain.inl" @@ -83,51 +83,52 @@ int EAMain(int argc, char* argv[]) TestApplication testSuite("EASTL Unit Tests", argc, argv); - testSuite.AddTest("TypeTraits", TestTypeTraits); - testSuite.AddTest("Extra", TestExtra); - testSuite.AddTest("Functional", TestFunctional); - testSuite.AddTest("Utility", TestUtility); + testSuite.AddTest("TypeTraits", TestTypeTraits); + testSuite.AddTest("TestCppCXTypeTraits", TestCppCXTypeTraits); + testSuite.AddTest("Extra", TestExtra); + testSuite.AddTest("Functional", TestFunctional); + testSuite.AddTest("Utility", TestUtility); #if EASTL_TUPLE_ENABLED - testSuite.AddTest("Tuple", TestTuple); + testSuite.AddTest("Tuple", TestTuple); #endif // EASTL_TUPLE_ENABLED - testSuite.AddTest("Memory", TestMemory); - testSuite.AddTest("Allocator", TestAllocator); - testSuite.AddTest("Random", TestRandom); - testSuite.AddTest("NumericLimits", TestNumericLimits); - testSuite.AddTest("Iterator", TestIterator); - testSuite.AddTest("Bitset", TestBitset); - testSuite.AddTest("SmartPtr", TestSmartPtr); - testSuite.AddTest("List", TestList); - testSuite.AddTest("ListMap", TestListMap); - testSuite.AddTest("FixedList", TestFixedList); - testSuite.AddTest("SList", TestSList); - testSuite.AddTest("FixedSList", TestFixedSList); - testSuite.AddTest("IntrusiveList", TestIntrusiveList); - testSuite.AddTest("IntrusiveSList", TestIntrusiveSList); - testSuite.AddTest("String", TestString); - testSuite.AddTest("FixedString", TestFixedString); - testSuite.AddTest("Array", TestArray); - testSuite.AddTest("Vector", TestVector); - testSuite.AddTest("FixedVector", TestFixedVector); - testSuite.AddTest("Deque", TestDeque); - testSuite.AddTest("Map", TestMap); - testSuite.AddTest("FixedMap", TestFixedMap); - testSuite.AddTest("Set", TestSet); - testSuite.AddTest("FixedSet", TestFixedSet); - testSuite.AddTest("Hash", TestHash); - testSuite.AddTest("FixedHash", TestFixedHash); - testSuite.AddTest("IntrusiveHash", TestIntrusiveHash); - testSuite.AddTest("VectorMap", TestVectorMap); - testSuite.AddTest("VectorSet", TestVectorSet); - testSuite.AddTest("Algorithm", TestAlgorithm); - testSuite.AddTest("Sort", TestSort); - testSuite.AddTest("Heap", TestHeap); - testSuite.AddTest("RingBuffer", TestRingBuffer); - testSuite.AddTest("SparseMatrix", TestSparseMatrix); - testSuite.AddTest("IntrusiveSDList",TestIntrusiveSDList); - testSuite.AddTest("BitVector", TestBitVector); - testSuite.AddTest("Ratio", TestRatio); - testSuite.AddTest("Chrono", TestChrono); + testSuite.AddTest("Memory", TestMemory); + testSuite.AddTest("Allocator", TestAllocator); + testSuite.AddTest("Random", TestRandom); + testSuite.AddTest("NumericLimits", TestNumericLimits); + testSuite.AddTest("Iterator", TestIterator); + testSuite.AddTest("Bitset", TestBitset); + testSuite.AddTest("SmartPtr", TestSmartPtr); + testSuite.AddTest("List", TestList); + testSuite.AddTest("ListMap", TestListMap); + testSuite.AddTest("FixedList", TestFixedList); + testSuite.AddTest("SList", TestSList); + testSuite.AddTest("FixedSList", TestFixedSList); + testSuite.AddTest("IntrusiveList", TestIntrusiveList); + testSuite.AddTest("IntrusiveSList", TestIntrusiveSList); + testSuite.AddTest("String", TestString); + testSuite.AddTest("FixedString", TestFixedString); + testSuite.AddTest("Array", TestArray); + testSuite.AddTest("Vector", TestVector); + testSuite.AddTest("FixedVector", TestFixedVector); + testSuite.AddTest("Deque", TestDeque); + testSuite.AddTest("Map", TestMap); + testSuite.AddTest("FixedMap", TestFixedMap); + testSuite.AddTest("Set", TestSet); + testSuite.AddTest("FixedSet", TestFixedSet); + testSuite.AddTest("Hash", TestHash); + testSuite.AddTest("FixedHash", TestFixedHash); + testSuite.AddTest("IntrusiveHash", TestIntrusiveHash); + testSuite.AddTest("VectorMap", TestVectorMap); + testSuite.AddTest("VectorSet", TestVectorSet); + testSuite.AddTest("Algorithm", TestAlgorithm); + testSuite.AddTest("Sort", TestSort); + testSuite.AddTest("Heap", TestHeap); + testSuite.AddTest("RingBuffer", TestRingBuffer); + testSuite.AddTest("SparseMatrix", TestSparseMatrix); + testSuite.AddTest("IntrusiveSDList", TestIntrusiveSDList); + testSuite.AddTest("BitVector", TestBitVector); + testSuite.AddTest("Ratio", TestRatio); + testSuite.AddTest("Chrono", TestChrono); nErrorCount += testSuite.Run();