xref: /oneTBB/test/tbb/test_concurrent_map.cpp (revision 478de5b1)
151c0b2f7Stbbdev /*
2b15aabb3Stbbdev     Copyright (c) 2005-2021 Intel Corporation
351c0b2f7Stbbdev 
451c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev     you may not use this file except in compliance with the License.
651c0b2f7Stbbdev     You may obtain a copy of the License at
751c0b2f7Stbbdev 
851c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev 
1051c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev     See the License for the specific language governing permissions and
1451c0b2f7Stbbdev     limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev #ifndef NOMINMAX
1751c0b2f7Stbbdev #define NOMINMAX
1851c0b2f7Stbbdev #endif
1951c0b2f7Stbbdev #include <tbb/concurrent_map.h>
2051c0b2f7Stbbdev #include "common/concurrent_ordered_common.h"
2151c0b2f7Stbbdev 
2251c0b2f7Stbbdev //! \file test_concurrent_map.cpp
2351c0b2f7Stbbdev //! \brief Test for [containers.concurrent_map containers.concurrent_multimap] specifications
2451c0b2f7Stbbdev 
2551c0b2f7Stbbdev template <typename... Args>
2651c0b2f7Stbbdev struct AllowMultimapping<tbb::concurrent_multimap<Args...>> : std::true_type {};
2751c0b2f7Stbbdev 
2851c0b2f7Stbbdev template <typename Key, typename Mapped>
2951c0b2f7Stbbdev using MyAllocator = LocalCountingAllocator<std::allocator<std::pair<const Key, Mapped>>>;
3051c0b2f7Stbbdev 
3151c0b2f7Stbbdev using move_support_tests::FooWithAssign;
3251c0b2f7Stbbdev 
3351c0b2f7Stbbdev using map_type = tbb::concurrent_map<int, int, std::less<int>, MyAllocator<int, int>>;
3451c0b2f7Stbbdev using multimap_type = tbb::concurrent_multimap<int, int, std::less<int>, MyAllocator<int, int>>;
3551c0b2f7Stbbdev using checked_map_type = tbb::concurrent_map<int, CheckType<int>, std::less<int>, MyAllocator<int, CheckType<int>>>;
3651c0b2f7Stbbdev using checked_multimap_type = tbb::concurrent_multimap<int, CheckType<int>, std::less<int>, MyAllocator<int, CheckType<int>>>;
3751c0b2f7Stbbdev using greater_map_type = tbb::concurrent_map<int, int, std::greater<int>, MyAllocator<int, int>>;
3851c0b2f7Stbbdev using greater_multimap_type = tbb::concurrent_multimap<int, int, std::greater<int>, MyAllocator<int, int>>;
3951c0b2f7Stbbdev using checked_state_map_type = tbb::concurrent_map<intptr_t, FooWithAssign, std::less<intptr_t>,
4051c0b2f7Stbbdev                                                    MyAllocator<intptr_t, FooWithAssign>>;
4151c0b2f7Stbbdev using checked_state_multimap_type = tbb::concurrent_multimap<intptr_t, FooWithAssign, std::less<intptr_t>,
4251c0b2f7Stbbdev                                                              MyAllocator<intptr_t, FooWithAssign>>;
4351c0b2f7Stbbdev 
4451c0b2f7Stbbdev template <>
4551c0b2f7Stbbdev struct SpecialTests<map_type> {
TestSpecialTests4651c0b2f7Stbbdev     static void Test() {
4751c0b2f7Stbbdev         SpecialMapTests<map_type>();
4851c0b2f7Stbbdev     }
4951c0b2f7Stbbdev };
5051c0b2f7Stbbdev 
5151c0b2f7Stbbdev template <>
5251c0b2f7Stbbdev struct SpecialTests<multimap_type> {
TestSpecialTests5351c0b2f7Stbbdev     static void Test() {
5451c0b2f7Stbbdev         SpecialMultiMapTests<multimap_type>();
5551c0b2f7Stbbdev     }
5651c0b2f7Stbbdev };
5751c0b2f7Stbbdev 
5851c0b2f7Stbbdev struct COMapTraits : OrderedMoveTraitsBase {
5951c0b2f7Stbbdev     template <typename T, typename Allocator>
6051c0b2f7Stbbdev     using container_type = tbb::concurrent_map<T, T, std::less<T>, Allocator>;
6151c0b2f7Stbbdev 
6251c0b2f7Stbbdev     template <typename T>
6351c0b2f7Stbbdev     using container_value_type = std::pair<const T, T>;
6451c0b2f7Stbbdev 
6551c0b2f7Stbbdev     using init_iterator_type = move_support_tests::FooPairIterator;
6651c0b2f7Stbbdev }; // struct COMapTraits
6751c0b2f7Stbbdev 
6851c0b2f7Stbbdev struct COMultimapTraits : OrderedMoveTraitsBase {
6951c0b2f7Stbbdev     template <typename T, typename Allocator>
7051c0b2f7Stbbdev     using container_type = tbb::concurrent_multimap<T, T, std::less<T>, Allocator>;
7151c0b2f7Stbbdev 
7251c0b2f7Stbbdev     template <typename T>
7351c0b2f7Stbbdev     using container_value_type = std::pair<const T, T>;
7451c0b2f7Stbbdev 
7551c0b2f7Stbbdev     using init_iterator_type = move_support_tests::FooPairIterator;
7651c0b2f7Stbbdev }; // struct COMultimapTraits
7751c0b2f7Stbbdev 
7851c0b2f7Stbbdev struct OrderedMapTypesTester {
7951c0b2f7Stbbdev     template <bool DefCtorPresent, typename ValueType>
checkOrderedMapTypesTester8051c0b2f7Stbbdev     void check( const std::list<ValueType>& lst ) {
8151c0b2f7Stbbdev         using key_type = typename ValueType::first_type;
8251c0b2f7Stbbdev         using mapped_type = typename ValueType::second_type;
8351c0b2f7Stbbdev 
8451c0b2f7Stbbdev         TypeTester<DefCtorPresent, tbb::concurrent_map<key_type, mapped_type>>(lst);
8551c0b2f7Stbbdev         TypeTester<DefCtorPresent, tbb::concurrent_multimap<key_type, mapped_type>>(lst);
8651c0b2f7Stbbdev     }
8751c0b2f7Stbbdev }; // struct OrderedMapTypesTester
8851c0b2f7Stbbdev 
test_specific_types()8951c0b2f7Stbbdev void test_specific_types() {
9051c0b2f7Stbbdev     test_map_specific_types<OrderedMapTypesTester>();
9151c0b2f7Stbbdev 
9251c0b2f7Stbbdev     // Regression test for a problem with excessive requirements of emplace()
9351c0b2f7Stbbdev     test_emplace_insert<tbb::concurrent_map<int*, test::unique_ptr<int>>,std::false_type>
9451c0b2f7Stbbdev                        (new int, new int);
9551c0b2f7Stbbdev     test_emplace_insert<tbb::concurrent_multimap<int*, test::unique_ptr<int>>,std::false_type>
9651c0b2f7Stbbdev                        (new int, new int);
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev 
9951c0b2f7Stbbdev // Regression test for an issue in lock free algorithms
10051c0b2f7Stbbdev // In some cases this test hangs due to broken skip list internal structure on levels > 1
10151c0b2f7Stbbdev // This issue was resolved by adding index_number into the skip list node
test_cycles_absense()10251c0b2f7Stbbdev void test_cycles_absense() {
10351c0b2f7Stbbdev     for (std::size_t execution = 0; execution != 10; ++execution) {
10451c0b2f7Stbbdev         tbb::concurrent_multimap<int, int> mmap;
10551c0b2f7Stbbdev         std::vector<int> v(2);
10651c0b2f7Stbbdev         int vector_size = int(v.size());
10751c0b2f7Stbbdev 
10851c0b2f7Stbbdev         for (int i = 0; i != vector_size; ++i) {
10951c0b2f7Stbbdev             v[i] = i;
11051c0b2f7Stbbdev         }
11151c0b2f7Stbbdev         size_t num_threads = 4; // Can be changed to 2 for debugging
11251c0b2f7Stbbdev 
11351c0b2f7Stbbdev         utils::NativeParallelFor(num_threads, [&](size_t) {
11451c0b2f7Stbbdev             for (int i = 0; i != vector_size; ++i) {
11551c0b2f7Stbbdev                 mmap.emplace(i, i);
11651c0b2f7Stbbdev             }
11751c0b2f7Stbbdev         });
11851c0b2f7Stbbdev 
11951c0b2f7Stbbdev         for (int i = 0; i != vector_size; ++i) {
12051c0b2f7Stbbdev             REQUIRE(mmap.count(i) == num_threads);
12151c0b2f7Stbbdev         }
12251c0b2f7Stbbdev     }
12351c0b2f7Stbbdev }
12451c0b2f7Stbbdev 
12551c0b2f7Stbbdev //! \brief \ref error_guessing
12651c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with greater compare") {
12751c0b2f7Stbbdev     test_basic<greater_map_type>();
12851c0b2f7Stbbdev }
12951c0b2f7Stbbdev 
13051c0b2f7Stbbdev //! \brief \ref error_guessing
13151c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with greater compare") {
13251c0b2f7Stbbdev     test_basic<greater_multimap_type>();
13351c0b2f7Stbbdev }
13451c0b2f7Stbbdev 
13551c0b2f7Stbbdev //! \brief \ref resource_usage
13651c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with elements ctor and dtor check") {
13751c0b2f7Stbbdev     Checker<checked_map_type::value_type> checker;
13851c0b2f7Stbbdev     test_basic<checked_map_type>();
13951c0b2f7Stbbdev }
14051c0b2f7Stbbdev 
14151c0b2f7Stbbdev //! \brief \ref resource_usage
14251c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with elements ctor and dtor check") {
14351c0b2f7Stbbdev     Checker<checked_multimap_type::value_type> checker;
14451c0b2f7Stbbdev     test_basic<checked_multimap_type>();
14551c0b2f7Stbbdev }
14651c0b2f7Stbbdev 
14751c0b2f7Stbbdev //! \brief \ref resource_usage
14851c0b2f7Stbbdev TEST_CASE("basic test for concurrent_map with elements state check") {
14951c0b2f7Stbbdev     test_basic<checked_state_map_type, /*CheckState = */std::true_type>();
15051c0b2f7Stbbdev }
15151c0b2f7Stbbdev 
15251c0b2f7Stbbdev //! \brief \ref resource_usage
15351c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multimap with elements state check") {
15451c0b2f7Stbbdev     test_basic<checked_state_multimap_type, /*CheckState = */std::true_type>();
15551c0b2f7Stbbdev }
15651c0b2f7Stbbdev 
15751c0b2f7Stbbdev //! \brief \ref error_guessing
15851c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with greater compare") {
15951c0b2f7Stbbdev     test_concurrent<greater_map_type>();
16051c0b2f7Stbbdev }
16151c0b2f7Stbbdev 
16251c0b2f7Stbbdev //! \brief \ref error_guessing
16351c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with greater compare") {
16451c0b2f7Stbbdev     test_concurrent<greater_multimap_type>();
16551c0b2f7Stbbdev }
16651c0b2f7Stbbdev 
16751c0b2f7Stbbdev //! \brief \ref resource_usage
16851c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with elements ctor and dtor check") {
16951c0b2f7Stbbdev     Checker<checked_map_type::value_type> checker;
17051c0b2f7Stbbdev     test_concurrent<checked_map_type>();
17151c0b2f7Stbbdev }
17251c0b2f7Stbbdev 
17351c0b2f7Stbbdev //! \brief \ref resource_usage
17451c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with elements ctor and dtor check") {
17551c0b2f7Stbbdev     Checker<checked_multimap_type::value_type> checker;
17651c0b2f7Stbbdev     test_concurrent<checked_multimap_type>();
17751c0b2f7Stbbdev }
17851c0b2f7Stbbdev 
17951c0b2f7Stbbdev //! \brief \ref resource_usage
18051c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_map with elements state check") {
18151c0b2f7Stbbdev     test_concurrent<checked_state_map_type>();
18251c0b2f7Stbbdev }
18351c0b2f7Stbbdev 
18451c0b2f7Stbbdev //! \brief \ref resource_usage
18551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with elements state check") {
18651c0b2f7Stbbdev     test_concurrent<checked_state_multimap_type>();
18751c0b2f7Stbbdev }
18851c0b2f7Stbbdev 
18951c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
19051c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap no unique keys") {
19151c0b2f7Stbbdev     test_concurrent<multimap_type>(true);
19251c0b2f7Stbbdev }
19351c0b2f7Stbbdev 
19451c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
19551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multimap with greater compare and no unique keys") {
19651c0b2f7Stbbdev     test_concurrent<greater_multimap_type>(true);
19751c0b2f7Stbbdev }
19851c0b2f7Stbbdev 
19951c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
20051c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_map") {
20151c0b2f7Stbbdev     test_range_based_for_support<map_type>();
20251c0b2f7Stbbdev }
20351c0b2f7Stbbdev 
20451c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
20551c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_multimap") {
20651c0b2f7Stbbdev     test_range_based_for_support<multimap_type>();
20751c0b2f7Stbbdev }
20851c0b2f7Stbbdev 
20951c0b2f7Stbbdev //! \brief \ref regression
21051c0b2f7Stbbdev TEST_CASE("concurrent_map/multimap with specific key/mapped types") {
21151c0b2f7Stbbdev     test_specific_types();
21251c0b2f7Stbbdev }
21351c0b2f7Stbbdev 
21451c0b2f7Stbbdev // TODO: add test with scoped_allocator_adaptor with broken macro
21551c0b2f7Stbbdev 
21651c0b2f7Stbbdev //! \brief \ref regression
21751c0b2f7Stbbdev TEST_CASE("broken internal structure for multimap") {
21851c0b2f7Stbbdev     test_cycles_absense();
21951c0b2f7Stbbdev }
22051c0b2f7Stbbdev 
22151c0b2f7Stbbdev //! \brief \ref error_guessing
22251c0b2f7Stbbdev TEST_CASE("concurrent_map::swap with not always equal allocator") {
22351c0b2f7Stbbdev     using not_always_equal_alloc_map_type = tbb::concurrent_map<int, int, std::less<int>,
22451c0b2f7Stbbdev                                                                 NotAlwaysEqualAllocator<std::pair<const int, int>>>;
22551c0b2f7Stbbdev     test_swap_not_always_equal_allocator<not_always_equal_alloc_map_type>();
22651c0b2f7Stbbdev }
22751c0b2f7Stbbdev 
22851c0b2f7Stbbdev //! \brief \ref error_guessing
22951c0b2f7Stbbdev TEST_CASE("concurrent_multimap::swap with not always equal allocator") {
23051c0b2f7Stbbdev     using not_always_equal_alloc_mmap_type = tbb::concurrent_multimap<int, int, std::less<int>,
23151c0b2f7Stbbdev                                                                       NotAlwaysEqualAllocator<std::pair<const int, int>>>;
23251c0b2f7Stbbdev     test_swap_not_always_equal_allocator<not_always_equal_alloc_mmap_type>();
23351c0b2f7Stbbdev }
23451c0b2f7Stbbdev 
23551c0b2f7Stbbdev #if TBB_USE_EXCEPTIONS
23651c0b2f7Stbbdev //! \brief \ref error_guessing
23751c0b2f7Stbbdev TEST_CASE("concurrent_map throwing copy constructor") {
23851c0b2f7Stbbdev     using exception_map_type = tbb::concurrent_map<ThrowOnCopy, ThrowOnCopy>;
23951c0b2f7Stbbdev     test_exception_on_copy_ctor<exception_map_type>();
24051c0b2f7Stbbdev }
24151c0b2f7Stbbdev 
24251c0b2f7Stbbdev //! \brief \ref error_guessing
24351c0b2f7Stbbdev TEST_CASE("concurrent_multimap throwing copy constructor") {
24451c0b2f7Stbbdev     using exception_mmap_type = tbb::concurrent_multimap<ThrowOnCopy, ThrowOnCopy>;
24551c0b2f7Stbbdev     test_exception_on_copy_ctor<exception_mmap_type>();
24651c0b2f7Stbbdev }
24751c0b2f7Stbbdev #endif // TBB_USE_EXCEPTIONS
248*478de5b1Stbbdev 
249*478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
250*478de5b1Stbbdev //! \brief \ref error_guessing
251*478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_map ranges") {
252*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::range_type>);
253*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_map<int, int>::const_range_type>);
254*478de5b1Stbbdev }
255*478de5b1Stbbdev 
256*478de5b1Stbbdev //! \brief \ref error_guessing
257*478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_multimap ranges") {
258*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::range_type>);
259*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_multimap<int, int>::const_range_type>);
260*478de5b1Stbbdev }
261*478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
262