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