xref: /oneTBB/test/tbb/test_concurrent_set.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 
2051c0b2f7Stbbdev #include <tbb/concurrent_set.h>
2151c0b2f7Stbbdev #include "common/concurrent_ordered_common.h"
2251c0b2f7Stbbdev 
2351c0b2f7Stbbdev //! \file test_concurrent_set.cpp
2451c0b2f7Stbbdev //! \brief Test for [containers.concurrent_set containers.concurrent_multiset] specifications
2551c0b2f7Stbbdev 
2651c0b2f7Stbbdev template <typename... Args>
2751c0b2f7Stbbdev struct AllowMultimapping<tbb::concurrent_multiset<Args...>> : std::true_type {};
2851c0b2f7Stbbdev 
2951c0b2f7Stbbdev template <typename Key>
3051c0b2f7Stbbdev using MyAllocator = LocalCountingAllocator<std::allocator<Key>>;
3151c0b2f7Stbbdev 
3251c0b2f7Stbbdev using move_support_tests::FooWithAssign;
3351c0b2f7Stbbdev 
3451c0b2f7Stbbdev using set_type = tbb::concurrent_set<int, std::less<int>, MyAllocator<int>>;
3551c0b2f7Stbbdev using multiset_type = tbb::concurrent_multiset<int, std::less<int>, MyAllocator<int>>;
3651c0b2f7Stbbdev using checked_set_type = tbb::concurrent_set<CheckType<int>, std::less<CheckType<int>>, MyAllocator<CheckType<int>>>;
3751c0b2f7Stbbdev using checked_multiset_type = tbb::concurrent_multiset<CheckType<int>, std::less<CheckType<int>>, MyAllocator<CheckType<int>>>;
3851c0b2f7Stbbdev using greater_set_type = tbb::concurrent_set<int, std::greater<int>, MyAllocator<int>>;
3951c0b2f7Stbbdev using greater_multiset_type = tbb::concurrent_multiset<int, std::greater<int>, MyAllocator<int>>;
4051c0b2f7Stbbdev using checked_state_set_type = tbb::concurrent_set<FooWithAssign, std::less<FooWithAssign>, MyAllocator<FooWithAssign>>;
4151c0b2f7Stbbdev using checked_state_multiset_type = tbb::concurrent_multiset<FooWithAssign, std::less<FooWithAssign>, MyAllocator<FooWithAssign>>;
4251c0b2f7Stbbdev 
4351c0b2f7Stbbdev struct COSetTraits : OrderedMoveTraitsBase {
4451c0b2f7Stbbdev     template <typename T, typename Allocator>
4551c0b2f7Stbbdev     using container_type = tbb::concurrent_set<T, std::less<T>, Allocator>;
4651c0b2f7Stbbdev 
4751c0b2f7Stbbdev     template <typename T>
4851c0b2f7Stbbdev     using container_value_type = T;
4951c0b2f7Stbbdev 
5051c0b2f7Stbbdev     using init_iterator_type = move_support_tests::FooIterator;
5151c0b2f7Stbbdev }; // struct COSetTraits
5251c0b2f7Stbbdev 
5351c0b2f7Stbbdev struct COMultisetTraits : OrderedMoveTraitsBase {
5451c0b2f7Stbbdev     template <typename T, typename Allocator>
5551c0b2f7Stbbdev     using container_type = tbb::concurrent_multiset<T, std::less<T>, Allocator>;
5651c0b2f7Stbbdev 
5751c0b2f7Stbbdev     template <typename T>
5851c0b2f7Stbbdev     using container_value_type = T;
5951c0b2f7Stbbdev 
6051c0b2f7Stbbdev     using init_iterator_type = move_support_tests::FooIterator;
6151c0b2f7Stbbdev }; // struct COMultisetTraits
6251c0b2f7Stbbdev 
6351c0b2f7Stbbdev struct OrderedSetTypesTester {
6451c0b2f7Stbbdev     template <bool DefCtorPresent, typename ValueType>
checkOrderedSetTypesTester6551c0b2f7Stbbdev     void check( const std::list<ValueType>& lst ) {
6651c0b2f7Stbbdev         TypeTester<DefCtorPresent, tbb::concurrent_set<ValueType>>(lst);
6751c0b2f7Stbbdev         TypeTester<DefCtorPresent, tbb::concurrent_multiset<ValueType>>(lst);
6851c0b2f7Stbbdev     }
6951c0b2f7Stbbdev }; // struct OrderedMapTypesTester
7051c0b2f7Stbbdev 
test_specific_types()7151c0b2f7Stbbdev void test_specific_types() {
7251c0b2f7Stbbdev     test_set_specific_types<OrderedSetTypesTester>();
7351c0b2f7Stbbdev 
7451c0b2f7Stbbdev     // Regression test for a problem with excessive requirements of emplace
7551c0b2f7Stbbdev     test_emplace_insert<tbb::concurrent_set<test::unique_ptr<int>>, std::false_type>
7651c0b2f7Stbbdev                        (new int, new int);
7751c0b2f7Stbbdev     test_emplace_insert<tbb::concurrent_multiset<test::unique_ptr<int>>, std::false_type>
7851c0b2f7Stbbdev                        (new int, new int);
7951c0b2f7Stbbdev }
8051c0b2f7Stbbdev 
8151c0b2f7Stbbdev // Regression test for an issue in lock free algorithms
8251c0b2f7Stbbdev // In some cases this test hangs due to broken skip list internal structure on levels > 1
8351c0b2f7Stbbdev // This issue was resolved by adding index_number into the skip list node
test_cycles_absense()8451c0b2f7Stbbdev void test_cycles_absense() {
8551c0b2f7Stbbdev     for (std::size_t execution = 0; execution != 10; ++execution) {
8651c0b2f7Stbbdev         tbb::concurrent_multiset<int> mset;
8751c0b2f7Stbbdev         std::vector<int> v(2);
8851c0b2f7Stbbdev         int vector_size = int(v.size());
8951c0b2f7Stbbdev 
9051c0b2f7Stbbdev         for (int i = 0; i != vector_size; ++i) {
9151c0b2f7Stbbdev             v[i] = int(i);
9251c0b2f7Stbbdev         }
9351c0b2f7Stbbdev         size_t num_threads = 4; // Can be changed to 2 for debugging
9451c0b2f7Stbbdev 
9551c0b2f7Stbbdev         utils::NativeParallelFor(num_threads, [&](size_t) {
9651c0b2f7Stbbdev             for (int i = 0; i != vector_size; ++i) {
9751c0b2f7Stbbdev                 mset.emplace(i);
9851c0b2f7Stbbdev             }
9951c0b2f7Stbbdev         });
10051c0b2f7Stbbdev 
10151c0b2f7Stbbdev         for (int i = 0; i != vector_size; ++i) {
10251c0b2f7Stbbdev             REQUIRE(mset.count(i) == num_threads);
10351c0b2f7Stbbdev         }
10451c0b2f7Stbbdev     }
10551c0b2f7Stbbdev }
10651c0b2f7Stbbdev 
10751c0b2f7Stbbdev //! \brief \ref error_guessing
10851c0b2f7Stbbdev TEST_CASE("basic test for concurrent_set with greater compare") {
10951c0b2f7Stbbdev     test_basic<greater_set_type>();
11051c0b2f7Stbbdev }
11151c0b2f7Stbbdev 
11251c0b2f7Stbbdev //! \brief \ref error_guessing
11351c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multiset with greater compare") {
11451c0b2f7Stbbdev     test_basic<greater_multiset_type>();
11551c0b2f7Stbbdev }
11651c0b2f7Stbbdev 
11751c0b2f7Stbbdev //! \brief \ref resource_usage
11851c0b2f7Stbbdev TEST_CASE("basic test for concurrent_set with elements ctor and dtor check") {
11951c0b2f7Stbbdev     Checker<checked_set_type::value_type> checker;
12051c0b2f7Stbbdev     test_basic<checked_set_type>();
12151c0b2f7Stbbdev }
12251c0b2f7Stbbdev 
12351c0b2f7Stbbdev //! \brief \ref resource_usage
12451c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multiset with elements ctor and dtor check") {
12551c0b2f7Stbbdev     Checker<checked_multiset_type::value_type> checker;
12651c0b2f7Stbbdev     test_basic<checked_multiset_type>();
12751c0b2f7Stbbdev }
12851c0b2f7Stbbdev 
12951c0b2f7Stbbdev //! \brief \ref resource_usage
13051c0b2f7Stbbdev TEST_CASE("basic test for concurrent_set with elements state check") {
13151c0b2f7Stbbdev     test_basic<checked_state_set_type, /*CheckState = */std::true_type>();
13251c0b2f7Stbbdev }
13351c0b2f7Stbbdev 
13451c0b2f7Stbbdev //! \brief \ref resource_usage
13551c0b2f7Stbbdev TEST_CASE("basic test for concurrent_multiset with elements state check") {
13651c0b2f7Stbbdev     test_basic<checked_state_multiset_type, /*CheckState = */std::true_type>();
13751c0b2f7Stbbdev }
13851c0b2f7Stbbdev 
13951c0b2f7Stbbdev //! \brief \ref error_guessing
14051c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_set with greater compare") {
14151c0b2f7Stbbdev     test_concurrent<greater_set_type>();
14251c0b2f7Stbbdev }
14351c0b2f7Stbbdev 
14451c0b2f7Stbbdev //! \brief \ref error_guessing
14551c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multiset with greater compare") {
14651c0b2f7Stbbdev     test_concurrent<greater_multiset_type>();
14751c0b2f7Stbbdev }
14851c0b2f7Stbbdev 
14951c0b2f7Stbbdev //! \brief \ref resource_usage
15051c0b2f7Stbbdev TEST_CASE("multithreding support in concurrent_set with elements ctor and dtor check") {
15151c0b2f7Stbbdev     Checker<checked_set_type::value_type> checker;
15251c0b2f7Stbbdev     test_concurrent<checked_set_type>();
15351c0b2f7Stbbdev }
15451c0b2f7Stbbdev 
15551c0b2f7Stbbdev //! \brief \ref resource_usage
15651c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multiset with elements ctor and dtor check") {
15751c0b2f7Stbbdev     Checker<checked_multiset_type::value_type> checker;
15851c0b2f7Stbbdev     test_concurrent<checked_multiset_type>();
15951c0b2f7Stbbdev }
16051c0b2f7Stbbdev 
16151c0b2f7Stbbdev //! \brief \ref resource_usage
16251c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_set with elements state check") {
16351c0b2f7Stbbdev     test_concurrent<checked_state_set_type>();
16451c0b2f7Stbbdev }
16551c0b2f7Stbbdev 
16651c0b2f7Stbbdev //! \brief \ref resource_usage
16751c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multiset with elements state check") {
16851c0b2f7Stbbdev     test_concurrent<checked_state_multiset_type>();
16951c0b2f7Stbbdev }
17051c0b2f7Stbbdev 
17151c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
17251c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multiset with no unique keys") {
17351c0b2f7Stbbdev     test_concurrent<multiset_type>(true);
17451c0b2f7Stbbdev }
17551c0b2f7Stbbdev 
17651c0b2f7Stbbdev //! \brief \ref stress \ref error_guessing
17751c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_multiset with greater compare and no unique keys") {
17851c0b2f7Stbbdev     test_concurrent<greater_multiset_type>(true);
17951c0b2f7Stbbdev }
18051c0b2f7Stbbdev 
18151c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
18251c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_set") {
18351c0b2f7Stbbdev     test_range_based_for_support<set_type>();
18451c0b2f7Stbbdev }
18551c0b2f7Stbbdev 
18651c0b2f7Stbbdev //! \brief \ref interface \ref error_guessing
18751c0b2f7Stbbdev TEST_CASE("range based for support in concurrent_multiset") {
18851c0b2f7Stbbdev     test_range_based_for_support<multiset_type>();
18951c0b2f7Stbbdev }
19051c0b2f7Stbbdev 
19151c0b2f7Stbbdev //! \brief \ref regression
19251c0b2f7Stbbdev TEST_CASE("concurrent set/multiset with specific key types") {
19351c0b2f7Stbbdev     test_specific_types();
19451c0b2f7Stbbdev }
19551c0b2f7Stbbdev 
19651c0b2f7Stbbdev //! \brief \ref error_guessing
19751c0b2f7Stbbdev TEST_CASE("concurrent_set with std::scoped_allocator_adaptor") {
19851c0b2f7Stbbdev     test_scoped_allocator<COSetTraits>();
19951c0b2f7Stbbdev }
20051c0b2f7Stbbdev 
20151c0b2f7Stbbdev //! \brief \ref error_guessing
20251c0b2f7Stbbdev TEST_CASE("concurrent_multiset with std::scoped_allocator_adaptor") {
20351c0b2f7Stbbdev     test_scoped_allocator<COMultisetTraits>();
20451c0b2f7Stbbdev }
20551c0b2f7Stbbdev 
20651c0b2f7Stbbdev //! \brief \ref regression
20751c0b2f7Stbbdev TEST_CASE("broken internal structure for multiset") {
20851c0b2f7Stbbdev     test_cycles_absense();
20951c0b2f7Stbbdev }
21051c0b2f7Stbbdev 
21151c0b2f7Stbbdev //! \brief \ref error_guessing
21251c0b2f7Stbbdev TEST_CASE("concurrent_set::swap with not always equal allocator") {
21351c0b2f7Stbbdev     using not_always_equal_alloc_set_type = tbb::concurrent_set<int, std::less<int>, NotAlwaysEqualAllocator<int>>;
21451c0b2f7Stbbdev     test_swap_not_always_equal_allocator<not_always_equal_alloc_set_type>();
21551c0b2f7Stbbdev }
21651c0b2f7Stbbdev 
21751c0b2f7Stbbdev //! \brief \ref error_guessing
21851c0b2f7Stbbdev TEST_CASE("concurrent_multiset::swap with not always equal allocator") {
21951c0b2f7Stbbdev     using not_always_equal_alloc_mset_type = tbb::concurrent_multiset<int, std::less<int>, NotAlwaysEqualAllocator<int>>;
22051c0b2f7Stbbdev     test_swap_not_always_equal_allocator<not_always_equal_alloc_mset_type>();
22151c0b2f7Stbbdev }
22251c0b2f7Stbbdev 
22351c0b2f7Stbbdev #if TBB_USE_EXCEPTIONS
22451c0b2f7Stbbdev //! \brief \ref error_guessing
22551c0b2f7Stbbdev TEST_CASE("concurrent_set throwing copy constructor") {
22651c0b2f7Stbbdev     using exception_set_type = tbb::concurrent_set<ThrowOnCopy>;
22751c0b2f7Stbbdev     test_exception_on_copy_ctor<exception_set_type>();
22851c0b2f7Stbbdev }
22951c0b2f7Stbbdev 
23051c0b2f7Stbbdev //! \brief \ref error_guessing
23151c0b2f7Stbbdev TEST_CASE("concurrent_multiset throwing copy constructor") {
23251c0b2f7Stbbdev     using exception_mset_type = tbb::concurrent_multiset<ThrowOnCopy>;
23351c0b2f7Stbbdev     test_exception_on_copy_ctor<exception_mset_type>();
23451c0b2f7Stbbdev }
23551c0b2f7Stbbdev #endif // TBB_USE_EXCEPTIONS
236*478de5b1Stbbdev 
237*478de5b1Stbbdev #if __TBB_CPP20_CONCEPTS_PRESENT
238*478de5b1Stbbdev //! \brief \ref error_guessing
239*478de5b1Stbbdev TEST_CASE("container_range concept for concurrent_set ranges") {
240*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_set<int>::range_type>);
241*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_set<int>::const_range_type>);
242*478de5b1Stbbdev }
243*478de5b1Stbbdev 
244*478de5b1Stbbdev //! \brief \ref error_guessing
245*478de5b1Stbbdev TEST_CASE("container range concept for concurrent_multiset ranges") {
246*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_multiset<int>::range_type>);
247*478de5b1Stbbdev     static_assert(test_concepts::container_range<typename tbb::concurrent_multiset<int>::const_range_type>);
248*478de5b1Stbbdev }
249*478de5b1Stbbdev #endif // __TBB_CPP20_CONCEPTS_PRESENT
250