xref: /oneTBB/test/common/test_invoke.h (revision a088cfa0)
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