/* Copyright (c) 2005-2021 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include "common/utils_report.h" #include #include #include #include #include #include #include #include "oneapi/tbb/concurrent_hash_map.h" #include "oneapi/tbb/global_control.h" #include "oneapi/tbb/parallel_for.h" //! \file conformance_concurrent_hash_map.cpp //! \brief Test for [containers.concurrent_hash_map containers.tbb_hash_compare] specification /** Has tightly controlled interface so that we can verify that concurrent_hash_map uses only the required interface. */ class MyException : public std::bad_alloc { public: virtual const char *what() const throw() override { return "out of items limit"; } virtual ~MyException() throw() {} }; /** Has tightly controlled interface so that we can verify that concurrent_hash_map uses only the required interface. */ class MyKey { private: int key; friend class MyHashCompare; friend class YourHashCompare; public: MyKey() = default; MyKey( const MyKey& ) = default; void operator=( const MyKey& ) = delete; static MyKey make( int i ) { MyKey result; result.key = i; return result; } int value_of() const { return key; } }; std::atomic MyDataCount; long MyDataCountLimit = 0; class MyData { protected: friend class MyData2; int data; enum state_t { LIVE=0x1234, DEAD=0x5678 } my_state; void operator=( const MyData& ); // Deny access public: MyData(int i = 0) { my_state = LIVE; data = i; if (MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) { TBB_TEST_THROW(MyException{}); } ++MyDataCount; } MyData( const MyData& other ) { CHECK(other.my_state==LIVE); my_state = LIVE; data = other.data; if(MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) { TBB_TEST_THROW(MyException{}); } ++MyDataCount; } ~MyData() { --MyDataCount; my_state = DEAD; } static MyData make( int i ) { MyData result; result.data = i; return result; } int value_of() const { CHECK(my_state==LIVE); return data; } void set_value( int i ) { CHECK(my_state==LIVE); data = i; } bool operator==( const MyData& other ) const { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); return data == other.data; } }; class MyData2 : public MyData { public: MyData2( ) {} MyData2( const MyData2& other ) : MyData() { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); data = other.data; } MyData2( const MyData& other ) { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); data = other.data; } void operator=( const MyData& other ) { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); data = other.data; } void operator=( const MyData2& other ) { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); data = other.data; } bool operator==( const MyData2& other ) const { CHECK(other.my_state==LIVE); CHECK(my_state==LIVE); return data == other.data; } }; class MyHashCompare { public: bool equal( const MyKey& j, const MyKey& k ) const { return j.key==k.key; } std::size_t hash( const MyKey& k ) const { return k.key; } }; class YourHashCompare { public: bool equal( const MyKey& j, const MyKey& k ) const { return j.key==k.key; } std::size_t hash( const MyKey& ) const { return 1; } }; using test_allocator_type = StaticSharedCountingAllocator>>; using test_table_type = oneapi::tbb::concurrent_hash_map; using other_test_table_type = oneapi::tbb::concurrent_hash_map; template