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
17b15aabb3Stbbdev #if __INTEL_COMPILER && _MSC_VER
18b15aabb3Stbbdev #pragma warning(disable : 2586) // decorated name length exceeded, name was truncated
19b15aabb3Stbbdev #endif
20b15aabb3Stbbdev
2151c0b2f7Stbbdev #include <common/concurrent_priority_queue_common.h>
2251c0b2f7Stbbdev #include <common/initializer_list_support.h>
2351c0b2f7Stbbdev #include <common/container_move_support.h>
2451c0b2f7Stbbdev #include <common/containers_common.h>
25b15aabb3Stbbdev #include <common/test_comparisons.h>
2651c0b2f7Stbbdev #include <scoped_allocator>
2751c0b2f7Stbbdev
2851c0b2f7Stbbdev //! \file conformance_concurrent_priority_queue.cpp
2951c0b2f7Stbbdev //! \brief Test for [containers.concurrent_priority_queue] specification
3051c0b2f7Stbbdev
test_to_vector()3151c0b2f7Stbbdev void test_to_vector() {
3251c0b2f7Stbbdev using equality_comparison_helpers::toVector;
3351c0b2f7Stbbdev int array[] = {1, 5, 6, 8, 4, 7};
3449e08aacStbbdev oneapi::tbb::blocked_range<int*> range = utils::make_blocked_range(array);
3551c0b2f7Stbbdev std::vector<int> source(range.begin(), range.end());
3651c0b2f7Stbbdev
3749e08aacStbbdev oneapi::tbb::concurrent_priority_queue<int> q(source.begin(), source.end());
3851c0b2f7Stbbdev std::vector<int> from_cpq = toVector(q);
3951c0b2f7Stbbdev
4051c0b2f7Stbbdev std::sort(source.begin(), source.end());
4151c0b2f7Stbbdev REQUIRE_MESSAGE(source == from_cpq, "equality_comparison_helpers::toVector incorrectly copied items from CPQ");
4251c0b2f7Stbbdev }
4351c0b2f7Stbbdev
test_basic()4451c0b2f7Stbbdev void test_basic() {
4551c0b2f7Stbbdev const int NUMBER = 10;
4651c0b2f7Stbbdev utils::FastRandom<> rnd(1234);
4751c0b2f7Stbbdev
4851c0b2f7Stbbdev std::vector<int> arrInt;
4951c0b2f7Stbbdev for (int i = 0; i < NUMBER; ++i)
5051c0b2f7Stbbdev arrInt.emplace_back(rnd.get());
5151c0b2f7Stbbdev
5251c0b2f7Stbbdev type_tester(arrInt); // Test integers
5351c0b2f7Stbbdev }
5451c0b2f7Stbbdev
test_initializer_list()5551c0b2f7Stbbdev void test_initializer_list() {
5651c0b2f7Stbbdev using namespace initializer_list_support_tests;
5749e08aacStbbdev test_initializer_list_support<oneapi::tbb::concurrent_priority_queue<char>>({1, 2, 3, 4, 5});
5849e08aacStbbdev test_initializer_list_support<oneapi::tbb::concurrent_priority_queue<int>>({});
5951c0b2f7Stbbdev }
6051c0b2f7Stbbdev
6151c0b2f7Stbbdev struct SpecialMemberCalls {
6251c0b2f7Stbbdev std::size_t copy_ctor_called_times;
6351c0b2f7Stbbdev std::size_t move_ctor_called_times;
6451c0b2f7Stbbdev std::size_t copy_assign_called_times;
6551c0b2f7Stbbdev std::size_t move_assign_called_times;
6651c0b2f7Stbbdev }; // struct SpecialMemberCalls
6751c0b2f7Stbbdev
operator ==(const SpecialMemberCalls & lhs,const SpecialMemberCalls & rhs)6851c0b2f7Stbbdev bool operator==( const SpecialMemberCalls& lhs, const SpecialMemberCalls& rhs ) {
6951c0b2f7Stbbdev return lhs.copy_ctor_called_times == rhs.copy_ctor_called_times &&
7051c0b2f7Stbbdev lhs.move_ctor_called_times == rhs.move_ctor_called_times &&
7151c0b2f7Stbbdev lhs.copy_assign_called_times == rhs.copy_assign_called_times &&
7251c0b2f7Stbbdev lhs.move_assign_called_times == rhs.move_assign_called_times;
7351c0b2f7Stbbdev }
7451c0b2f7Stbbdev
75b15aabb3Stbbdev template <typename CounterType>
76b15aabb3Stbbdev struct MoveOperationTrackerBase {
77b15aabb3Stbbdev static CounterType copy_ctor_called_times;
78b15aabb3Stbbdev static CounterType move_ctor_called_times;
79b15aabb3Stbbdev static CounterType copy_assign_called_times;
80b15aabb3Stbbdev static CounterType move_assign_called_times;
8151c0b2f7Stbbdev
special_member_callsMoveOperationTrackerBase8251c0b2f7Stbbdev static SpecialMemberCalls special_member_calls() {
8351c0b2f7Stbbdev return SpecialMemberCalls{copy_ctor_called_times, move_ctor_called_times, copy_assign_called_times, move_assign_called_times};
8451c0b2f7Stbbdev }
85b15aabb3Stbbdev static CounterType value_counter;
8651c0b2f7Stbbdev std::size_t value;
8751c0b2f7Stbbdev
MoveOperationTrackerBaseMoveOperationTrackerBase88b15aabb3Stbbdev MoveOperationTrackerBase() : value(++value_counter) {}
MoveOperationTrackerBaseMoveOperationTrackerBase89b15aabb3Stbbdev explicit MoveOperationTrackerBase( const std::size_t val ) : value(val) {}
~MoveOperationTrackerBaseMoveOperationTrackerBase90b15aabb3Stbbdev ~MoveOperationTrackerBase() { value = 0; }
9151c0b2f7Stbbdev
MoveOperationTrackerBaseMoveOperationTrackerBase92b15aabb3Stbbdev MoveOperationTrackerBase( const MoveOperationTrackerBase& other ) : value(other.value) {
9351c0b2f7Stbbdev REQUIRE_MESSAGE(other.value, "The object has been moved or destroyed");
9451c0b2f7Stbbdev ++copy_ctor_called_times;
9551c0b2f7Stbbdev }
9651c0b2f7Stbbdev
MoveOperationTrackerBaseMoveOperationTrackerBase97b15aabb3Stbbdev MoveOperationTrackerBase( MoveOperationTrackerBase&& other ) noexcept : value(other.value) {
9851c0b2f7Stbbdev REQUIRE_MESSAGE(other.value, "The object has been moved or destroyed");
9951c0b2f7Stbbdev other.value = 0;
10051c0b2f7Stbbdev ++move_ctor_called_times;
10151c0b2f7Stbbdev }
10251c0b2f7Stbbdev
operator =MoveOperationTrackerBase103b15aabb3Stbbdev MoveOperationTrackerBase& operator=( const MoveOperationTrackerBase& other ) {
10451c0b2f7Stbbdev REQUIRE_MESSAGE(other.value, "The object has been moved or destroyed");
10551c0b2f7Stbbdev value = other.value;
10651c0b2f7Stbbdev ++copy_assign_called_times;
10751c0b2f7Stbbdev return *this;
10851c0b2f7Stbbdev }
10951c0b2f7Stbbdev
operator =MoveOperationTrackerBase110b15aabb3Stbbdev MoveOperationTrackerBase& operator=( MoveOperationTrackerBase&& other ) noexcept {
11151c0b2f7Stbbdev REQUIRE_MESSAGE(other.value, "The object has been moved or destroyed");
11251c0b2f7Stbbdev value = other.value;
11351c0b2f7Stbbdev other.value = 0;
11451c0b2f7Stbbdev ++move_assign_called_times;
11551c0b2f7Stbbdev return *this;
11651c0b2f7Stbbdev }
11751c0b2f7Stbbdev
operator <MoveOperationTrackerBase118b15aabb3Stbbdev bool operator<( const MoveOperationTrackerBase& other ) const {
11951c0b2f7Stbbdev REQUIRE_MESSAGE(value, "The object has been moved or destroyed");
12051c0b2f7Stbbdev REQUIRE_MESSAGE(other.value, "The object has been moved or destroyed");
12151c0b2f7Stbbdev return value < other.value;
12251c0b2f7Stbbdev }
123b15aabb3Stbbdev }; // struct MoveOperationTrackerBase
12451c0b2f7Stbbdev
125b15aabb3Stbbdev template<typename CounterType>
operator ==(const MoveOperationTrackerBase<CounterType> & lhs,const MoveOperationTrackerBase<CounterType> & rhs)126b15aabb3Stbbdev bool operator==( const MoveOperationTrackerBase<CounterType>& lhs, const MoveOperationTrackerBase<CounterType>& rhs ) {
12751c0b2f7Stbbdev return !(lhs < rhs) && !(rhs < lhs);
12851c0b2f7Stbbdev }
12951c0b2f7Stbbdev
130b15aabb3Stbbdev using MoveOperationTracker = MoveOperationTrackerBase<std::size_t>;
131b15aabb3Stbbdev using MoveOperationTrackerConc = MoveOperationTrackerBase<std::atomic<std::size_t>>;
132b15aabb3Stbbdev
133b15aabb3Stbbdev template <typename CounterType> CounterType MoveOperationTrackerBase<CounterType>::copy_ctor_called_times(0);
134b15aabb3Stbbdev template <typename CounterType> CounterType MoveOperationTrackerBase<CounterType>::move_ctor_called_times(0);
135b15aabb3Stbbdev template <typename CounterType> CounterType MoveOperationTrackerBase<CounterType>::copy_assign_called_times(0);
136b15aabb3Stbbdev template <typename CounterType> CounterType MoveOperationTrackerBase<CounterType>::move_assign_called_times(0);
137b15aabb3Stbbdev template <typename CounterType> CounterType MoveOperationTrackerBase<CounterType>::value_counter(0);
13851c0b2f7Stbbdev
13951c0b2f7Stbbdev template <typename Allocator = std::allocator<MoveOperationTracker>>
14051c0b2f7Stbbdev struct CPQSrcFixture {
14151c0b2f7Stbbdev CPQSrcFixture& operator=( const CPQSrcFixture& ) = delete;
14251c0b2f7Stbbdev
14351c0b2f7Stbbdev enum {default_container_size = 100};
14451c0b2f7Stbbdev using cpq_compare_type = std::less<MoveOperationTracker>;
14551c0b2f7Stbbdev using cpq_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<MoveOperationTracker>;
14649e08aacStbbdev using cpq_type = oneapi::tbb::concurrent_priority_queue<MoveOperationTracker, cpq_compare_type, cpq_allocator_type>;
14751c0b2f7Stbbdev
14851c0b2f7Stbbdev cpq_type cpq_src;
14951c0b2f7Stbbdev const std::size_t container_size;
15051c0b2f7Stbbdev
initCPQSrcFixture15151c0b2f7Stbbdev void init() {
15251c0b2f7Stbbdev std::size_t& mcct = MoveOperationTracker::move_ctor_called_times;
15351c0b2f7Stbbdev std::size_t& ccct = MoveOperationTracker::copy_ctor_called_times;
15451c0b2f7Stbbdev std::size_t& cact = MoveOperationTracker::copy_assign_called_times;
15551c0b2f7Stbbdev std::size_t& mact = MoveOperationTracker::move_assign_called_times;
15651c0b2f7Stbbdev mcct = ccct = cact = mact = 0;
15751c0b2f7Stbbdev
15851c0b2f7Stbbdev for (std::size_t i = 1; i <= container_size; ++i) {
15951c0b2f7Stbbdev cpq_src.push(MoveOperationTracker(i));
16051c0b2f7Stbbdev }
16151c0b2f7Stbbdev REQUIRE_MESSAGE(cpq_src.size() == container_size, "Error in test setup");
16251c0b2f7Stbbdev }
16351c0b2f7Stbbdev
CPQSrcFixtureCPQSrcFixture16451c0b2f7Stbbdev CPQSrcFixture( std::size_t size = default_container_size )
16551c0b2f7Stbbdev : CPQSrcFixture(typename cpq_type::allocator_type(), size) {}
16651c0b2f7Stbbdev
CPQSrcFixtureCPQSrcFixture16751c0b2f7Stbbdev CPQSrcFixture( const typename cpq_type::allocator_type& a, std::size_t size = default_container_size )
16851c0b2f7Stbbdev : cpq_src(a), container_size(size)
16951c0b2f7Stbbdev {
17051c0b2f7Stbbdev init();
17151c0b2f7Stbbdev }
17251c0b2f7Stbbdev }; // struct CPQSrcFixture
17351c0b2f7Stbbdev
test_steal_move_ctor()17451c0b2f7Stbbdev void test_steal_move_ctor() {
17551c0b2f7Stbbdev using fixture_type = CPQSrcFixture<>;
17651c0b2f7Stbbdev using container_type = typename fixture_type::cpq_type;
17751c0b2f7Stbbdev fixture_type fixture;
17851c0b2f7Stbbdev container_type src_copy{fixture.cpq_src};
17951c0b2f7Stbbdev
18051c0b2f7Stbbdev SpecialMemberCalls previous = MoveOperationTracker::special_member_calls();
18151c0b2f7Stbbdev container_type dst{std::move(fixture.cpq_src)};
18251c0b2f7Stbbdev REQUIRE_MESSAGE(previous == MoveOperationTracker::special_member_calls(), "Steal move ctor should not create any new elements");
18351c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during steal move");
18451c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during steal move");
18551c0b2f7Stbbdev }
18651c0b2f7Stbbdev
test_steal_move_ctor_with_allocator()18751c0b2f7Stbbdev void test_steal_move_ctor_with_allocator() {
18851c0b2f7Stbbdev using arena_fixture_type = move_support_tests::TwoMemoryArenasFixture<MoveOperationTracker>;
18951c0b2f7Stbbdev using fixture_type = CPQSrcFixture<arena_fixture_type::allocator_type>;
19051c0b2f7Stbbdev
19151c0b2f7Stbbdev arena_fixture_type arena_fixture(8 * fixture_type::default_container_size);
19251c0b2f7Stbbdev fixture_type fixture(arena_fixture.source_allocator);
19351c0b2f7Stbbdev fixture_type::cpq_type src_copy(fixture.cpq_src);
19451c0b2f7Stbbdev
19551c0b2f7Stbbdev SpecialMemberCalls previous = MoveOperationTracker::special_member_calls();
19651c0b2f7Stbbdev fixture_type::cpq_type dst(std::move(fixture.cpq_src), arena_fixture.source_allocator);
19751c0b2f7Stbbdev REQUIRE_MESSAGE(previous == MoveOperationTracker::special_member_calls(), "Steal move ctor should not create any new elements");
19851c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during steal move");
19951c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during steal move");
20051c0b2f7Stbbdev }
20151c0b2f7Stbbdev
test_per_element_move_ctor_with_allocator()20251c0b2f7Stbbdev void test_per_element_move_ctor_with_allocator() {
20351c0b2f7Stbbdev using arena_fixture_type = move_support_tests::TwoMemoryArenasFixture<MoveOperationTracker>;
20451c0b2f7Stbbdev using fixture_type = CPQSrcFixture<arena_fixture_type::allocator_type>;
20551c0b2f7Stbbdev
20651c0b2f7Stbbdev arena_fixture_type arena_fixture(8 * fixture_type::default_container_size);
20751c0b2f7Stbbdev fixture_type fixture(arena_fixture.source_allocator);
20851c0b2f7Stbbdev fixture_type::cpq_type src_copy(fixture.cpq_src);
20951c0b2f7Stbbdev
21051c0b2f7Stbbdev SpecialMemberCalls move_ctor_called_cpq_size_times = MoveOperationTracker::special_member_calls();
21151c0b2f7Stbbdev move_ctor_called_cpq_size_times.move_ctor_called_times += fixture.container_size;
21251c0b2f7Stbbdev
21351c0b2f7Stbbdev fixture_type::cpq_type dst(std::move(fixture.cpq_src), arena_fixture.dst_allocator);
21451c0b2f7Stbbdev REQUIRE_MESSAGE(move_ctor_called_cpq_size_times == MoveOperationTracker::special_member_calls(),
21551c0b2f7Stbbdev "Per element move ctor should move initialize all new elements");
21651c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during move");
21751c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during move");
21851c0b2f7Stbbdev }
21951c0b2f7Stbbdev
test_steal_move_assign_operator()22051c0b2f7Stbbdev void test_steal_move_assign_operator() {
22151c0b2f7Stbbdev using fixture_type = CPQSrcFixture<>;
22251c0b2f7Stbbdev
22351c0b2f7Stbbdev fixture_type fixture;
22451c0b2f7Stbbdev fixture_type::cpq_type src_copy(fixture.cpq_src);
22551c0b2f7Stbbdev
22651c0b2f7Stbbdev fixture_type::cpq_type dst;
22751c0b2f7Stbbdev SpecialMemberCalls previous = MoveOperationTracker::special_member_calls();
22851c0b2f7Stbbdev dst = std::move(fixture.cpq_src);
22951c0b2f7Stbbdev
23051c0b2f7Stbbdev REQUIRE_MESSAGE(previous == MoveOperationTracker::special_member_calls(), "Steal move assign operator should not create any new elements");
23151c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during steal move assignment");
23251c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during steal move assignment");
23351c0b2f7Stbbdev }
23451c0b2f7Stbbdev
test_steal_move_assign_operator_with_stateful_allocator()23551c0b2f7Stbbdev void test_steal_move_assign_operator_with_stateful_allocator() {
23651c0b2f7Stbbdev // Use stateful allocator which is propagated on move assignment
23751c0b2f7Stbbdev using arena_fixture_type = move_support_tests::TwoMemoryArenasFixture<MoveOperationTracker, /*POCMA = */std::true_type>;
23851c0b2f7Stbbdev using fixture_type = CPQSrcFixture<arena_fixture_type::allocator_type>;
23951c0b2f7Stbbdev
24051c0b2f7Stbbdev arena_fixture_type arena_fixture(8 * fixture_type::default_container_size);
24151c0b2f7Stbbdev fixture_type fixture(arena_fixture.source_allocator);
24251c0b2f7Stbbdev fixture_type::cpq_type src_copy(fixture.cpq_src);
24351c0b2f7Stbbdev fixture_type::cpq_type dst(arena_fixture.dst_allocator);
24451c0b2f7Stbbdev
24551c0b2f7Stbbdev SpecialMemberCalls previous = MoveOperationTracker::special_member_calls();
24651c0b2f7Stbbdev dst = std::move(fixture.cpq_src);
24751c0b2f7Stbbdev REQUIRE_MESSAGE(previous == MoveOperationTracker::special_member_calls(), "Steal move assign operator should not create any new elements");
24851c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during steal move assignment");
24951c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during steal move assignment");
25051c0b2f7Stbbdev }
25151c0b2f7Stbbdev
test_per_element_move_assign_operator()25251c0b2f7Stbbdev void test_per_element_move_assign_operator() {
25351c0b2f7Stbbdev // Use stateful allocator which is not prepagated on move assignment
25451c0b2f7Stbbdev using arena_fixture_type = move_support_tests::TwoMemoryArenasFixture<MoveOperationTracker, /*POCMA = */std::false_type>;
25551c0b2f7Stbbdev using fixture_type = CPQSrcFixture<arena_fixture_type::allocator_type>;
25651c0b2f7Stbbdev
25751c0b2f7Stbbdev arena_fixture_type arena_fixture(8 * fixture_type::default_container_size);
25851c0b2f7Stbbdev fixture_type fixture(arena_fixture.source_allocator);
25951c0b2f7Stbbdev fixture_type::cpq_type src_copy(fixture.cpq_src);
26051c0b2f7Stbbdev fixture_type::cpq_type dst(arena_fixture.dst_allocator);
26151c0b2f7Stbbdev
26251c0b2f7Stbbdev SpecialMemberCalls move_ctor_called_cpq_size_times = MoveOperationTracker::special_member_calls();
26351c0b2f7Stbbdev move_ctor_called_cpq_size_times.move_ctor_called_times += fixture.container_size;
26451c0b2f7Stbbdev dst = std::move(fixture.cpq_src);
26551c0b2f7Stbbdev REQUIRE_MESSAGE(move_ctor_called_cpq_size_times == MoveOperationTracker::special_member_calls(),
26651c0b2f7Stbbdev "Per element move assignment should move initialize all new elements");
26751c0b2f7Stbbdev REQUIRE_MESSAGE(dst == src_copy, "cpq content changed during per element move assignment");
26851c0b2f7Stbbdev REQUIRE_MESSAGE(!(dst != src_copy), "cpq content changed during per element move assignment");
26951c0b2f7Stbbdev }
27051c0b2f7Stbbdev
test_cpq_move_constructor()27151c0b2f7Stbbdev void test_cpq_move_constructor() {
27251c0b2f7Stbbdev test_steal_move_ctor();
27351c0b2f7Stbbdev test_steal_move_ctor_with_allocator();
27451c0b2f7Stbbdev test_per_element_move_ctor_with_allocator();
27551c0b2f7Stbbdev }
27651c0b2f7Stbbdev
test_cpq_move_assignment()27751c0b2f7Stbbdev void test_cpq_move_assignment() {
27851c0b2f7Stbbdev test_steal_move_assign_operator();
27951c0b2f7Stbbdev test_steal_move_assign_operator_with_stateful_allocator();
28051c0b2f7Stbbdev test_per_element_move_assign_operator();
28151c0b2f7Stbbdev }
28251c0b2f7Stbbdev
28351c0b2f7Stbbdev
28451c0b2f7Stbbdev struct NoDefaultCtorType {
28551c0b2f7Stbbdev NoDefaultCtorType() = delete;
28651c0b2f7Stbbdev
NoDefaultCtorTypeNoDefaultCtorType28751c0b2f7Stbbdev NoDefaultCtorType( std::size_t val1, std::size_t val2 ) : value1(val1), value2(val2) {}
operator <NoDefaultCtorType28851c0b2f7Stbbdev bool operator<(const NoDefaultCtorType& other) const {
28951c0b2f7Stbbdev return value1 + value2 < other.value1 + other.value2;
29051c0b2f7Stbbdev }
29151c0b2f7Stbbdev
29251c0b2f7Stbbdev std::size_t value1, value2;
29351c0b2f7Stbbdev }; // struct NoDefaultCtorType
29451c0b2f7Stbbdev
29551c0b2f7Stbbdev struct ForwardInEmplaceTester {
29651c0b2f7Stbbdev int a;
29751c0b2f7Stbbdev static bool move_ctor_called;
29851c0b2f7Stbbdev static bool move_assign_called;
29951c0b2f7Stbbdev
ForwardInEmplaceTesterForwardInEmplaceTester30051c0b2f7Stbbdev ForwardInEmplaceTester( int val ) : a(val) {}
30151c0b2f7Stbbdev ForwardInEmplaceTester( const ForwardInEmplaceTester& ) = default;
30251c0b2f7Stbbdev ForwardInEmplaceTester( ForwardInEmplaceTester&& ) = default;
30351c0b2f7Stbbdev
ForwardInEmplaceTesterForwardInEmplaceTester30451c0b2f7Stbbdev ForwardInEmplaceTester( ForwardInEmplaceTester&& obj, int val ) : a(obj.a) {
30551c0b2f7Stbbdev move_ctor_called = true;
30651c0b2f7Stbbdev obj.a = val;
30751c0b2f7Stbbdev }
30851c0b2f7Stbbdev
30951c0b2f7Stbbdev ForwardInEmplaceTester& operator=( const ForwardInEmplaceTester& ) = default;
31051c0b2f7Stbbdev
operator =ForwardInEmplaceTester31151c0b2f7Stbbdev ForwardInEmplaceTester& operator=( ForwardInEmplaceTester&& obj ) {
31251c0b2f7Stbbdev a = obj.a;
31351c0b2f7Stbbdev move_assign_called = true;
31451c0b2f7Stbbdev return *this;
31551c0b2f7Stbbdev }
31651c0b2f7Stbbdev
operator <ForwardInEmplaceTester31751c0b2f7Stbbdev bool operator<( const ForwardInEmplaceTester& ) const { return true; }
31851c0b2f7Stbbdev }; // struct ForwardInEmplaceTester
31951c0b2f7Stbbdev
32051c0b2f7Stbbdev bool ForwardInEmplaceTester::move_ctor_called = false;
32151c0b2f7Stbbdev bool ForwardInEmplaceTester::move_assign_called = false;
32251c0b2f7Stbbdev
test_move_support_in_push_pop()32351c0b2f7Stbbdev void test_move_support_in_push_pop() {
32451c0b2f7Stbbdev std::size_t& mcct = MoveOperationTracker::move_ctor_called_times;
32551c0b2f7Stbbdev std::size_t& ccct = MoveOperationTracker::copy_ctor_called_times;
32651c0b2f7Stbbdev std::size_t& cact = MoveOperationTracker::copy_assign_called_times;
32751c0b2f7Stbbdev std::size_t& mact = MoveOperationTracker::move_assign_called_times;
32851c0b2f7Stbbdev mcct = ccct = cact = mact = 0;
32951c0b2f7Stbbdev
33049e08aacStbbdev oneapi::tbb::concurrent_priority_queue<MoveOperationTracker> q1;
33151c0b2f7Stbbdev
33251c0b2f7Stbbdev REQUIRE_MESSAGE(mcct == 0, "Value must be zero-initialized");
33351c0b2f7Stbbdev REQUIRE_MESSAGE(ccct == 0, "Value must be zero-initialized");
33451c0b2f7Stbbdev
33551c0b2f7Stbbdev q1.push(MoveOperationTracker{});
33651c0b2f7Stbbdev REQUIRE_MESSAGE(mcct > 0, "Not working push(T&&)");
33751c0b2f7Stbbdev REQUIRE_MESSAGE(ccct == 0, "Copying of arg occurred during push(T&&)");
33851c0b2f7Stbbdev
33951c0b2f7Stbbdev MoveOperationTracker ob;
34051c0b2f7Stbbdev const std::size_t prev_mcct = mcct;
34151c0b2f7Stbbdev q1.push(std::move(ob));
34251c0b2f7Stbbdev REQUIRE_MESSAGE(mcct > prev_mcct, "Not working push(T&&)");
34351c0b2f7Stbbdev REQUIRE_MESSAGE(ccct == 0, "Copying of arg occurred during push(T&&)");
34451c0b2f7Stbbdev
34551c0b2f7Stbbdev REQUIRE_MESSAGE(cact == 0, "Copy assignment called during push(T&&)");
34651c0b2f7Stbbdev const std::size_t prev_mact = mact;
34751c0b2f7Stbbdev q1.try_pop(ob);
34851c0b2f7Stbbdev REQUIRE_MESSAGE(cact == 0, "Copy assignment called during try_pop(T&)");
34951c0b2f7Stbbdev REQUIRE_MESSAGE(mact > prev_mact, "Move assignment was not called during try_pop(T&)");
35051c0b2f7Stbbdev
35149e08aacStbbdev oneapi::tbb::concurrent_priority_queue<NoDefaultCtorType> q2;
35251c0b2f7Stbbdev q2.emplace(15, 3);
35351c0b2f7Stbbdev q2.emplace(2, 35);
35451c0b2f7Stbbdev q2.emplace(8, 8);
35551c0b2f7Stbbdev
35651c0b2f7Stbbdev NoDefaultCtorType o(0, 0);
35751c0b2f7Stbbdev q2.try_pop(o);
35851c0b2f7Stbbdev REQUIRE_MESSAGE((o.value1 == 2 && o.value2 == 35), "Unexpected data popped; possible emplace() failure");
35951c0b2f7Stbbdev q2.try_pop(o);
36051c0b2f7Stbbdev REQUIRE_MESSAGE((o.value1 == 15 && o.value2 == 3), "Unexpected data popped; possible emplace() failure");
36151c0b2f7Stbbdev q2.try_pop(o);
36251c0b2f7Stbbdev REQUIRE_MESSAGE((o.value1 == 8 && o.value2 == 8), "Unexpected data popped; possible emplace() failure");
36351c0b2f7Stbbdev REQUIRE_MESSAGE(!q2.try_pop(o), "The queue should be empty");
36451c0b2f7Stbbdev
36549e08aacStbbdev oneapi::tbb::concurrent_priority_queue<ForwardInEmplaceTester> q3;
36651c0b2f7Stbbdev REQUIRE(ForwardInEmplaceTester::move_ctor_called == false);
36751c0b2f7Stbbdev q3.emplace(ForwardInEmplaceTester{5}, 2);
36851c0b2f7Stbbdev REQUIRE_MESSAGE(ForwardInEmplaceTester::move_ctor_called == true, "Not used std::forward in emplace()");
36951c0b2f7Stbbdev ForwardInEmplaceTester obj(0);
37051c0b2f7Stbbdev q3.try_pop(obj);
37151c0b2f7Stbbdev
37251c0b2f7Stbbdev REQUIRE_MESSAGE(ForwardInEmplaceTester::move_assign_called == true, "Not used move assignment in try_pop");
37351c0b2f7Stbbdev REQUIRE_MESSAGE(obj.a == 5, "Not used std::forward in emplace");
37451c0b2f7Stbbdev REQUIRE_MESSAGE(!q3.try_pop(obj), "The queue should be empty");
37551c0b2f7Stbbdev }
37651c0b2f7Stbbdev
37751c0b2f7Stbbdev // Comparator with assert in default ctor
37851c0b2f7Stbbdev template <typename T>
37951c0b2f7Stbbdev class LessA : public std::less<T> {
38051c0b2f7Stbbdev public:
LessA(bool no_assert=false)38151c0b2f7Stbbdev explicit LessA( bool no_assert = false ) {
38251c0b2f7Stbbdev REQUIRE_MESSAGE(no_assert, "Default ctor should not be called");
38351c0b2f7Stbbdev }
38451c0b2f7Stbbdev }; // class LessA
38551c0b2f7Stbbdev
38651c0b2f7Stbbdev // TODO: consider use of TEST_SUITE for these tests
38751c0b2f7Stbbdev // TODO: combine with the constructors test from the common part
test_ctors_dtor_accessors()38851c0b2f7Stbbdev void test_ctors_dtor_accessors() {
38951c0b2f7Stbbdev std::vector<int> v;
39051c0b2f7Stbbdev std::allocator<int> a;
39151c0b2f7Stbbdev
39249e08aacStbbdev using cpq_type = oneapi::tbb::concurrent_priority_queue<int, std::less<int>>;
39349e08aacStbbdev using cpq_with_compare_type = oneapi::tbb::concurrent_priority_queue<int, LessA<int>>;
39449e08aacStbbdev using cpq_with_compare_and_allocator_type = oneapi::tbb::concurrent_priority_queue<int, LessA<int>, std::allocator<int>>;
39551c0b2f7Stbbdev
39651c0b2f7Stbbdev LessA<int> l(true);
39751c0b2f7Stbbdev
39851c0b2f7Stbbdev // Test default ctor
39951c0b2f7Stbbdev cpq_type cpq1;
40051c0b2f7Stbbdev REQUIRE_MESSAGE(cpq1.size() == 0, "Failed size test for default ctor");
40151c0b2f7Stbbdev REQUIRE_MESSAGE(cpq1.empty(), "Failed empty test for default ctor");
40251c0b2f7Stbbdev
40351c0b2f7Stbbdev // Test capacity ctor
40451c0b2f7Stbbdev cpq_type cpq2(42);
40551c0b2f7Stbbdev REQUIRE_MESSAGE(cpq2.size() == 0, "Failed size test for capacity ctor");
40651c0b2f7Stbbdev REQUIRE_MESSAGE(cpq2.empty(), "Failed empty test for capacity ctor");
40751c0b2f7Stbbdev
40851c0b2f7Stbbdev // Test compare ctor
40951c0b2f7Stbbdev cpq_with_compare_type cpq3(l);
41051c0b2f7Stbbdev REQUIRE_MESSAGE(cpq3.size() == 0, "Failed size test for compare ctor");
41151c0b2f7Stbbdev REQUIRE_MESSAGE(cpq3.empty(), "Failed empty test for compare ctor");
41251c0b2f7Stbbdev
41351c0b2f7Stbbdev // Test compare+allocator ctor
41451c0b2f7Stbbdev cpq_with_compare_and_allocator_type cpq4(l, a);
41551c0b2f7Stbbdev REQUIRE_MESSAGE(cpq4.size() == 0, "Failed size test for compare+allocator ctor");
41651c0b2f7Stbbdev REQUIRE_MESSAGE(cpq4.empty(), "Failed empty test for compare+allocator ctor");
41751c0b2f7Stbbdev
41851c0b2f7Stbbdev // Test capacity+compare ctor
41951c0b2f7Stbbdev cpq_with_compare_type cpq5(42, l);
42051c0b2f7Stbbdev REQUIRE_MESSAGE(cpq5.size() == 0, "Failed size test for capacity+compare ctor");
42151c0b2f7Stbbdev REQUIRE_MESSAGE(cpq5.empty(), "Failed empty test for capacity+compare ctor");
42251c0b2f7Stbbdev
42351c0b2f7Stbbdev // Test capacity+compare+allocator ctor
42451c0b2f7Stbbdev cpq_with_compare_and_allocator_type cpq6(42, l, a);
42551c0b2f7Stbbdev REQUIRE_MESSAGE(cpq6.size() == 0, "Failed size test for capacity+compare+allocator ctor");
42651c0b2f7Stbbdev REQUIRE_MESSAGE(cpq6.empty(), "Failed empty test for capacity+compare+allocator ctor");
42751c0b2f7Stbbdev
42851c0b2f7Stbbdev // Test half-open range ctor
42951c0b2f7Stbbdev for (int i = 0; i < 42; ++i) {
43051c0b2f7Stbbdev v.emplace_back(i);
43151c0b2f7Stbbdev }
43251c0b2f7Stbbdev using equality_comparison_helpers::toVector;
43351c0b2f7Stbbdev cpq_type cpq7(v.begin(), v.end());
43451c0b2f7Stbbdev REQUIRE_MESSAGE(cpq7.size() == 42, "Failed size test for half-open range ctor");
43551c0b2f7Stbbdev REQUIRE_MESSAGE(!cpq7.empty(), "Failed empty test for half-open range test");
43651c0b2f7Stbbdev REQUIRE_MESSAGE(v == toVector(cpq7), "Failed equality test for half-open range ctor");
43751c0b2f7Stbbdev
43851c0b2f7Stbbdev // Test half-open range + compare ctor
43951c0b2f7Stbbdev cpq_with_compare_type cpq8(v.begin(), v.end(), l);
44051c0b2f7Stbbdev REQUIRE_MESSAGE(cpq8.size() == 42, "Failed size test for half-open range+compare ctor");
44151c0b2f7Stbbdev REQUIRE_MESSAGE(!cpq8.empty(), "Failed empty test for half-open range+compare ctor");
44251c0b2f7Stbbdev REQUIRE_MESSAGE(v == toVector(cpq8), "Failed equality test for half-open range+compare ctor");
44351c0b2f7Stbbdev
44451c0b2f7Stbbdev // Test copy ctor
44551c0b2f7Stbbdev cpq_type cpq9(cpq7);
44651c0b2f7Stbbdev REQUIRE_MESSAGE(cpq9.size() == cpq7.size(), "Failed size test for copy ctor");
44751c0b2f7Stbbdev REQUIRE_MESSAGE(!cpq9.empty(), "Failed empty test for copy ctor");
44851c0b2f7Stbbdev REQUIRE_MESSAGE(cpq9 == cpq7, "Failed equality test for copy ctor");
44951c0b2f7Stbbdev }
45051c0b2f7Stbbdev
test_assignment_clear_swap()45151c0b2f7Stbbdev void test_assignment_clear_swap() {
45251c0b2f7Stbbdev using equality_comparison_helpers::toVector;
45349e08aacStbbdev using cpq_type = oneapi::tbb::concurrent_priority_queue<int, std::less<int>>;
45451c0b2f7Stbbdev std::vector<int> v;
45551c0b2f7Stbbdev int e;
45651c0b2f7Stbbdev
45751c0b2f7Stbbdev for( int i = 0; i < 42; ++i )
45851c0b2f7Stbbdev v.emplace_back(i);
45951c0b2f7Stbbdev
46051c0b2f7Stbbdev cpq_type q(v.begin(), v.end());
46151c0b2f7Stbbdev cpq_type qo;
46251c0b2f7Stbbdev
46351c0b2f7Stbbdev // Test assignment
46451c0b2f7Stbbdev qo = q;
46551c0b2f7Stbbdev REQUIRE_MESSAGE(qo.size() == 42, "Failed assignment size test");
46651c0b2f7Stbbdev REQUIRE_MESSAGE(!qo.empty(), "Failed assignment empty test");
46751c0b2f7Stbbdev REQUIRE_MESSAGE(v == toVector(qo), "Failed assignment equality test");
46851c0b2f7Stbbdev REQUIRE_MESSAGE(qo == q, "Failed assignment equality test");
46951c0b2f7Stbbdev REQUIRE_MESSAGE(!(qo != q), "Failed assignment inequality test");
47051c0b2f7Stbbdev
47151c0b2f7Stbbdev cpq_type assigned_q;
47251c0b2f7Stbbdev // Testing assign member function
47351c0b2f7Stbbdev assigned_q.assign(v.begin(), v.end());
47451c0b2f7Stbbdev REQUIRE_MESSAGE(assigned_q.size() == 42, "Failed assign size test");
47551c0b2f7Stbbdev REQUIRE_MESSAGE(!assigned_q.empty(), "Failed assign empty test");
47651c0b2f7Stbbdev REQUIRE_MESSAGE(v == toVector(assigned_q), "Failed assign equality test");
47751c0b2f7Stbbdev
47851c0b2f7Stbbdev // Testing clear()
47951c0b2f7Stbbdev q.clear();
48051c0b2f7Stbbdev REQUIRE_MESSAGE(q.size() == 0, "Failed clear size test");
48151c0b2f7Stbbdev REQUIRE_MESSAGE(q.empty(), "Failed clear empty test");
48251c0b2f7Stbbdev
48351c0b2f7Stbbdev // Test assignment again
48451c0b2f7Stbbdev for (std::size_t i = 0; i < 5; ++i)
48551c0b2f7Stbbdev qo.try_pop(e);
48651c0b2f7Stbbdev
48751c0b2f7Stbbdev q = qo;
48851c0b2f7Stbbdev REQUIRE_MESSAGE(q.size() == 37, "Failed assignment size test");
48951c0b2f7Stbbdev REQUIRE_MESSAGE(!q.empty(), "Failed assignment empty test");
49051c0b2f7Stbbdev
49151c0b2f7Stbbdev for (std::size_t i = 0; i < 5; ++i)
49251c0b2f7Stbbdev qo.try_pop(e);
49351c0b2f7Stbbdev
49451c0b2f7Stbbdev q.swap(qo);
49551c0b2f7Stbbdev
49651c0b2f7Stbbdev REQUIRE_MESSAGE(q.size() == 32, "Failed swap size test");
49751c0b2f7Stbbdev REQUIRE_MESSAGE(!q.empty(), "Failed swap empty test");
49851c0b2f7Stbbdev REQUIRE_MESSAGE(qo.size() == 37, "Failed swap size test");
49951c0b2f7Stbbdev REQUIRE_MESSAGE(!qo.empty(), "Failed swap empty test");
50051c0b2f7Stbbdev }
50151c0b2f7Stbbdev
test_serial_push_pop()50251c0b2f7Stbbdev void test_serial_push_pop() {
50349e08aacStbbdev oneapi::tbb::concurrent_priority_queue<int, std::less<int>> q(MAX_ITER);
50451c0b2f7Stbbdev int e = 42;
50551c0b2f7Stbbdev int prev = INT_MAX;
50651c0b2f7Stbbdev std::size_t count = 0;
50751c0b2f7Stbbdev
50851c0b2f7Stbbdev // Test serial push
50951c0b2f7Stbbdev for (std::size_t i = 0; i < MAX_ITER; ++i) {
51051c0b2f7Stbbdev push_selector(q, e, i);
51151c0b2f7Stbbdev e = e*-1 + int(i);
51251c0b2f7Stbbdev }
51351c0b2f7Stbbdev
51451c0b2f7Stbbdev REQUIRE_MESSAGE(q.size() == MAX_ITER, "Failed push size test");
51551c0b2f7Stbbdev REQUIRE_MESSAGE(!q.empty(), "Failed push empty test");
51651c0b2f7Stbbdev
51751c0b2f7Stbbdev // Test serial pop
51851c0b2f7Stbbdev while(!q.empty()) {
51951c0b2f7Stbbdev REQUIRE_MESSAGE(q.try_pop(e), "Failed pop test");
52051c0b2f7Stbbdev REQUIRE_MESSAGE(prev >= e, "Failed pop priority test");
52151c0b2f7Stbbdev prev = e;
52251c0b2f7Stbbdev ++count;
52351c0b2f7Stbbdev
52451c0b2f7Stbbdev REQUIRE_MESSAGE(q.size() == MAX_ITER - count, "Failed pop size test");
52551c0b2f7Stbbdev REQUIRE_MESSAGE((!q.empty() || count == MAX_ITER), "Failed pop empty test");
52651c0b2f7Stbbdev }
52751c0b2f7Stbbdev REQUIRE_MESSAGE(!q.try_pop(e), "Failed: successful pop from the empty queue");
52851c0b2f7Stbbdev }
52951c0b2f7Stbbdev
test_concurrent(std::size_t n)53051c0b2f7Stbbdev void test_concurrent(std::size_t n) {
53151c0b2f7Stbbdev test_parallel_push_pop<std::less<int>>(n, INT_MAX, INT_MIN);
53251c0b2f7Stbbdev test_parallel_push_pop<std::less<int>>(n, (unsigned char)CHAR_MAX, (unsigned char)CHAR_MIN);
53351c0b2f7Stbbdev
53451c0b2f7Stbbdev test_flogger<std::less<int>, int>(n);
53551c0b2f7Stbbdev test_flogger<std::less<int>, unsigned char>(n);
53651c0b2f7Stbbdev
537b15aabb3Stbbdev MoveOperationTrackerConc::copy_assign_called_times = 0;
538b15aabb3Stbbdev test_flogger<std::less<MoveOperationTrackerConc>, MoveOperationTrackerConc>(n);
539b15aabb3Stbbdev REQUIRE_MESSAGE(MoveOperationTrackerConc::copy_assign_called_times == 0, "Copy assignment called during try_pop");
54051c0b2f7Stbbdev }
54151c0b2f7Stbbdev
test_multithreading()54251c0b2f7Stbbdev void test_multithreading() {
54351c0b2f7Stbbdev for (std::size_t n = utils::MinThread; n != utils::MaxThread; ++n) {
54451c0b2f7Stbbdev test_concurrent(n);
54551c0b2f7Stbbdev }
54651c0b2f7Stbbdev }
54751c0b2f7Stbbdev
54851c0b2f7Stbbdev struct CPQTraits {
54951c0b2f7Stbbdev template <typename T>
55051c0b2f7Stbbdev using container_value_type = T;
55151c0b2f7Stbbdev
55251c0b2f7Stbbdev template <typename T, typename Allocator>
55349e08aacStbbdev using container_type = oneapi::tbb::concurrent_priority_queue<T, std::less<T>, Allocator>;
55451c0b2f7Stbbdev }; // struct CPQTraits
55551c0b2f7Stbbdev
55651c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
55751c0b2f7Stbbdev template <template <typename...>typename TQueue>
TestDeductionGuides()55851c0b2f7Stbbdev void TestDeductionGuides() {
55951c0b2f7Stbbdev using ComplexType = const std::string*;
56051c0b2f7Stbbdev std::string s("s");
56151c0b2f7Stbbdev std::vector<ComplexType> v;
56251c0b2f7Stbbdev auto l = {ComplexType(&s), ComplexType(&s) };
56351c0b2f7Stbbdev
56451c0b2f7Stbbdev // check TQueue(InputIterator, InputIterator)
56551c0b2f7Stbbdev TQueue qv(v.begin(), v.end());
56651c0b2f7Stbbdev static_assert(std::is_same<decltype(qv), TQueue<ComplexType> >::value);
56751c0b2f7Stbbdev
56851c0b2f7Stbbdev // check TQueue(InputIterator, InputIterator, Allocator)
56951c0b2f7Stbbdev TQueue qva(v.begin(), v.end(), std::allocator<ComplexType>());
57051c0b2f7Stbbdev static_assert(std::is_same<decltype(qva), TQueue<ComplexType, std::less<ComplexType>,
57151c0b2f7Stbbdev std::allocator<ComplexType>>>::value);
57251c0b2f7Stbbdev
57351c0b2f7Stbbdev // check TQueue(InputIterator, InputIterator, Compare)
57451c0b2f7Stbbdev TQueue qvc(v.begin(), v.end(), LessA<ComplexType>(true));
57551c0b2f7Stbbdev static_assert(std::is_same<decltype(qvc), TQueue<ComplexType, LessA<ComplexType>>>::value);
57651c0b2f7Stbbdev
57751c0b2f7Stbbdev // check TQueue(InputIterator, InputIterator, Compare, Allocator)
57851c0b2f7Stbbdev TQueue qvca(v.begin(), v.end(), LessA<ComplexType>(true), std::allocator<ComplexType>());
57951c0b2f7Stbbdev static_assert(std::is_same<decltype(qvca), TQueue<ComplexType, LessA<ComplexType>,
58051c0b2f7Stbbdev std::allocator<ComplexType>>>::value);
58151c0b2f7Stbbdev
58251c0b2f7Stbbdev // check TQueue(std::initializer_list)
58351c0b2f7Stbbdev TQueue ql(l);
58451c0b2f7Stbbdev static_assert(std::is_same<decltype(ql), TQueue<ComplexType>>::value);
58551c0b2f7Stbbdev
58651c0b2f7Stbbdev // check TQueue(std::initializer_list, Allocator)
58751c0b2f7Stbbdev TQueue qla(l, std::allocator<ComplexType>());
58851c0b2f7Stbbdev static_assert(std::is_same<decltype(qla), TQueue<ComplexType, std::less<ComplexType>,
58951c0b2f7Stbbdev std::allocator<ComplexType>>>::value);
59051c0b2f7Stbbdev
59151c0b2f7Stbbdev // check TQueue(std::initializer_list, Compare)
59251c0b2f7Stbbdev TQueue qlc(l, LessA<ComplexType>(true));
59351c0b2f7Stbbdev static_assert(std::is_same<decltype(qlc), TQueue<ComplexType, LessA<ComplexType>>>::value);
59451c0b2f7Stbbdev
59551c0b2f7Stbbdev // check TQueue(std::initializer_list, Compare, Allocator)
59651c0b2f7Stbbdev TQueue qlca(l, LessA<ComplexType>(true), std::allocator<ComplexType>());
59751c0b2f7Stbbdev static_assert(std::is_same<decltype(qlca), TQueue<ComplexType, LessA<ComplexType>,
59851c0b2f7Stbbdev std::allocator<ComplexType>>>::value);
59951c0b2f7Stbbdev
60051c0b2f7Stbbdev // check TQueue(TQueue &)
60151c0b2f7Stbbdev TQueue qc(qv);
60251c0b2f7Stbbdev static_assert(std::is_same<decltype(qv), decltype(qv)>::value);
60351c0b2f7Stbbdev
60451c0b2f7Stbbdev // check TQueue(TQueue &, Allocator)
60551c0b2f7Stbbdev TQueue qca(qva, std::allocator<ComplexType>());
60651c0b2f7Stbbdev static_assert(std::is_same<decltype(qca), decltype(qva)>::value);
60751c0b2f7Stbbdev
60851c0b2f7Stbbdev // check TQueue(TQueue &&)
60951c0b2f7Stbbdev TQueue qm(std::move(qv));
61051c0b2f7Stbbdev static_assert(std::is_same<decltype(qm), decltype(qv)>::value);
61151c0b2f7Stbbdev
61251c0b2f7Stbbdev // check TQueue(TQueue &&, Allocator)
61351c0b2f7Stbbdev TQueue qma(std::move(qva), std::allocator<ComplexType>());
61451c0b2f7Stbbdev static_assert(std::is_same<decltype(qma), decltype(qva)>::value);
61551c0b2f7Stbbdev }
61651c0b2f7Stbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
61751c0b2f7Stbbdev
618b15aabb3Stbbdev template <typename CPQType>
TestComparisonsBasic()619b15aabb3Stbbdev void TestComparisonsBasic() {
620b15aabb3Stbbdev using comparisons_testing::testEqualityComparisons;
621b15aabb3Stbbdev CPQType c1, c2;
622b15aabb3Stbbdev testEqualityComparisons</*ExpectEqual = */true>(c1, c2);
623b15aabb3Stbbdev
624b15aabb3Stbbdev c1.emplace(1);
625b15aabb3Stbbdev testEqualityComparisons</*ExpectEqual = */false>(c1, c2);
626b15aabb3Stbbdev
627b15aabb3Stbbdev c2.emplace(1);
628b15aabb3Stbbdev testEqualityComparisons</*ExpectEqual = */true>(c1, c2);
629b15aabb3Stbbdev }
630b15aabb3Stbbdev
631b15aabb3Stbbdev template <typename TwoWayComparableCPQType>
TestTwoWayComparableCPQ()632b15aabb3Stbbdev void TestTwoWayComparableCPQ() {
633b15aabb3Stbbdev TwoWayComparableCPQType c1, c2;
634b15aabb3Stbbdev c1.emplace(1);
635b15aabb3Stbbdev c2.emplace(1);
636b15aabb3Stbbdev comparisons_testing::TwoWayComparable::reset();
637b15aabb3Stbbdev REQUIRE_MESSAGE(c1 == c2, "Incorrect operator == result");
638b15aabb3Stbbdev comparisons_testing::check_equality_comparison();
639b15aabb3Stbbdev REQUIRE_MESSAGE(!(c1 != c2), "Incorrect operator != result");
640b15aabb3Stbbdev comparisons_testing::check_equality_comparison();
641b15aabb3Stbbdev }
642b15aabb3Stbbdev
TestCPQComparisons()643b15aabb3Stbbdev void TestCPQComparisons() {
644b15aabb3Stbbdev using integral_container = oneapi::tbb::concurrent_priority_queue<int>;
645b15aabb3Stbbdev using two_way_comparable_container = oneapi::tbb::concurrent_priority_queue<comparisons_testing::TwoWayComparable>;
646b15aabb3Stbbdev
647b15aabb3Stbbdev TestComparisonsBasic<integral_container>();
648b15aabb3Stbbdev TestComparisonsBasic<two_way_comparable_container>();
649b15aabb3Stbbdev TestTwoWayComparableCPQ<two_way_comparable_container>();
650b15aabb3Stbbdev }
651b15aabb3Stbbdev
65251c0b2f7Stbbdev // Testing basic operations with concurrent_priority_queue with integral value type
65351c0b2f7Stbbdev //! \brief \ref interface \ref requirement
65451c0b2f7Stbbdev TEST_CASE("basic test for concurrent_priority_queue") {
65551c0b2f7Stbbdev test_to_vector(); // Test concurrent_priority_queue helper
65651c0b2f7Stbbdev test_basic();
65751c0b2f7Stbbdev }
65851c0b2f7Stbbdev
65951c0b2f7Stbbdev // Testing std::initializer_list interfaces in concurrent_priority_queue
66051c0b2f7Stbbdev //! \brief \ref interface \ref requirement
66151c0b2f7Stbbdev TEST_CASE("std::initializer_list support in concurrent_priority_queue") {
66251c0b2f7Stbbdev test_initializer_list();
66351c0b2f7Stbbdev }
66451c0b2f7Stbbdev
66551c0b2f7Stbbdev //! Testing concurrent_priority_queue moving constructors
66651c0b2f7Stbbdev //! \brief \ref interface \ref requirement
66751c0b2f7Stbbdev TEST_CASE("concurrent_priority_queue move constructor") {
66851c0b2f7Stbbdev test_cpq_move_constructor();
66951c0b2f7Stbbdev }
67051c0b2f7Stbbdev
67151c0b2f7Stbbdev //! Testing concurrent_priority_queue move assignment operator with different allocator types
67251c0b2f7Stbbdev //! \brief \ref interface \ref requirement
67351c0b2f7Stbbdev TEST_CASE("concurrent_priority_queue move assignment operator") {
67451c0b2f7Stbbdev test_cpq_move_assignment();
67551c0b2f7Stbbdev }
67651c0b2f7Stbbdev
67751c0b2f7Stbbdev //! Testing move semantics on basic push-pop operations
67851c0b2f7Stbbdev //! \brief \ref requirement
67951c0b2f7Stbbdev TEST_CASE("move semantics support on push-pop operations") {
68051c0b2f7Stbbdev test_move_support_in_push_pop();
68151c0b2f7Stbbdev }
68251c0b2f7Stbbdev
68351c0b2f7Stbbdev //! \brief \ref interface \ref requirement
68451c0b2f7Stbbdev TEST_CASE("constructors, destructor and accessors") {
68551c0b2f7Stbbdev test_ctors_dtor_accessors();
68651c0b2f7Stbbdev }
68751c0b2f7Stbbdev
68851c0b2f7Stbbdev //! \brief \ref interface \ref requirement
68951c0b2f7Stbbdev TEST_CASE("assignment, clear and swap operations") {
69051c0b2f7Stbbdev test_assignment_clear_swap();
69151c0b2f7Stbbdev }
69251c0b2f7Stbbdev
69351c0b2f7Stbbdev //! Testing push-pop operations in concurrent_priority_queue
69451c0b2f7Stbbdev //! \brief \ref requirement
69551c0b2f7Stbbdev TEST_CASE("serial push-pop") {
69651c0b2f7Stbbdev test_serial_push_pop();
69751c0b2f7Stbbdev }
69851c0b2f7Stbbdev
69951c0b2f7Stbbdev //! Testing push-pop operations in concurrent_priority_queue with multithreading
70051c0b2f7Stbbdev //! \brief \ref requirement
70151c0b2f7Stbbdev TEST_CASE("multithreading support in concurrent_priority_queue") {
70251c0b2f7Stbbdev test_multithreading();
70351c0b2f7Stbbdev }
70451c0b2f7Stbbdev
705*478de5b1Stbbdev #if !_MSC_VER || _MSC_VER > 1900
706*478de5b1Stbbdev // MSVC 2015 does not provide required level of allocator support for standard containers
707*478de5b1Stbbdev
70851c0b2f7Stbbdev //! \brief \ref requirement
70951c0b2f7Stbbdev TEST_CASE("std::allocator_traits support in concurrent_priority_queue") {
71051c0b2f7Stbbdev test_allocator_traits_support<CPQTraits>();
71151c0b2f7Stbbdev }
712*478de5b1Stbbdev #endif
71351c0b2f7Stbbdev
71451c0b2f7Stbbdev #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
71551c0b2f7Stbbdev //! Testing Class Template Argument Deduction in concurrent_priority_queue
71651c0b2f7Stbbdev //! \brief \ref interface \ref requirement
71751c0b2f7Stbbdev TEST_CASE("CTAD support in concurrent_priority_queue") {
71849e08aacStbbdev TestDeductionGuides<oneapi::tbb::concurrent_priority_queue>();
71951c0b2f7Stbbdev }
72051c0b2f7Stbbdev #endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
721b15aabb3Stbbdev
722b15aabb3Stbbdev //! \brief \ref interface \ref requirement
723b15aabb3Stbbdev TEST_CASE("concurrent_priority_queue iterator comparisons") {
724b15aabb3Stbbdev TestCPQComparisons();
725b15aabb3Stbbdev }
726