1 /*
2 Copyright (c) 2023 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #ifndef __TBB_test_common_test_invoke_H
18 #define __TBB_test_common_test_invoke_H
19
20 #include "test.h"
21 #include "oneapi/tbb/flow_graph.h"
22 #include "oneapi/tbb/blocked_range.h"
23
24 #if __TBB_CPP17_INVOKE_PRESENT
25 namespace test_invoke {
26
27 // Can be customized
28 template <typename T>
get_real_index(const T & obj)29 std::size_t get_real_index(const T& obj) {
30 return obj;
31 }
32
33 template <typename Value>
34 class SmartRange : public oneapi::tbb::blocked_range<Value> {
35 using base_range = oneapi::tbb::blocked_range<Value>;
36 public:
SmartRange(const Value & first,const Value & last)37 SmartRange(const Value& first, const Value& last) : base_range(first, last), change_vector(nullptr) {}
SmartRange(const Value & first,const Value & last,std::vector<std::size_t> & cv)38 SmartRange(const Value& first, const Value& last, std::vector<std::size_t>& cv)
39 : base_range(first, last), change_vector(&cv) {}
40
41 SmartRange(const SmartRange&) = default;
SmartRange(SmartRange & other,oneapi::tbb::split)42 SmartRange(SmartRange& other, oneapi::tbb::split)
43 : base_range(other, oneapi::tbb::split{}), change_vector(other.change_vector) {}
44
increase()45 void increase() const {
46 CHECK_MESSAGE(change_vector, "Attempt to operate with no associated vector");
47 for (std::size_t index = get_real_index(this->begin()); index != get_real_index(this->end()); ++index) {
48 ++(*change_vector)[index];
49 }
50 }
51
reduction(const Value & idx)52 Value reduction(const Value& idx) const {
53 Value result = idx;
54 for (std::size_t index = get_real_index(this->begin()); index != get_real_index(this->end()); ++index) {
55 result = result + Value(index);
56 }
57 return Value(result);
58 }
59
scan(const Value & idx,bool is_final_scan)60 Value scan(const Value& idx, bool is_final_scan) const {
61 CHECK_MESSAGE(change_vector, "Attempt to operate with no associated vector");
62 Value result = idx;
63 for (std::size_t index = get_real_index(this->begin()); index != get_real_index(this->end()); ++index) {
64 result = result + Value(index);
65 if (is_final_scan) (*change_vector)[index] = get_real_index(result);
66 }
67 return result;
68 }
69 private:
70 std::vector<std::size_t>* change_vector;
71 };
72
73 template <typename IDType>
74 class SmartID {
75 public:
SmartID()76 SmartID() : id(999), operate_signal_point(nullptr) {}
SmartID(std::size_t * sp)77 SmartID(std::size_t* sp) : id(999), operate_signal_point(sp) {}
78
SmartID(const IDType & n)79 SmartID(const IDType& n) : id(n), operate_signal_point(nullptr) {}
SmartID(const IDType & n,std::size_t * sp)80 SmartID(const IDType& n, std::size_t* sp) : id(n), operate_signal_point(sp) {}
81
get_id()82 IDType get_id() const { return id; }
get_id_ref()83 const IDType& get_id_ref() const { return id; }
84
85 private:
86 template <typename TupleOfPorts, std::size_t... Is>
send_id_impl(TupleOfPorts & ports,std::index_sequence<Is...>)87 void send_id_impl(TupleOfPorts& ports, std::index_sequence<Is...>) const {
88 (std::get<Is>(ports).try_put(id) , ...);
89 }
90 public:
91 template <typename TupleOfPorts>
send_id(TupleOfPorts & ports)92 void send_id(TupleOfPorts& ports) const {
93 send_id_impl(ports, std::make_index_sequence<std::tuple_size<TupleOfPorts>::value>());
94 }
95
96 template <typename GatewayType>
send_id_to_gateway(GatewayType & gateway)97 void send_id_to_gateway(GatewayType& gateway) const {
98 gateway.reserve_wait();
99 gateway.try_put(id);
100 gateway.release_wait();
101 }
102
operate()103 void operate() const {
104 CHECK_MESSAGE(operate_signal_point, "incorrect test setup");
105 ++(*operate_signal_point);
106 }
107
108 IDType id;
109 private:
110 std::size_t* operate_signal_point;
111 };
112
113 class SmartValue {
114 public:
SmartValue(std::size_t rv)115 SmartValue(std::size_t rv) : real_value(rv) {}
116 SmartValue(const SmartValue&) = default;
117 SmartValue& operator=(const SmartValue&) = default;
118
119 SmartValue operator+(const SmartValue& other) const {
120 return SmartValue{real_value + other.real_value};
121 }
122 std::size_t operator-(const SmartValue& other) const {
123 return real_value - other.real_value;
124 }
125
get()126 std::size_t get() const { return real_value; }
127
128 bool operator<(const SmartValue& other) const {
129 return real_value < other.real_value;
130 }
131
132 SmartValue& operator++() { ++real_value; return *this; }
133 private:
134 std::size_t real_value;
135 };
136
get_real_index(const SmartValue & value)137 std::size_t get_real_index(const SmartValue& value) {
138 return value.get();
139 }
140
141
142 } // namespace test_invoke
143
144 #endif // __TBB_CPP17_INVOKE_PRESENT
145 #endif // __TBB_test_common_test_invoke_H
146