C++ Library Extensions 2022.12.09
To help learn modern C++ programming
051-thread_count.cpp
Go to the documentation of this file.
1#include <tpf_parallel.hpp>
2#include <tpf_output.hpp>
3#include <tpf_safe_type.hpp>
5
6#include <execution>
7#include <thread>
8#include <sstream>
9
12
14{
15 size_t count = 100;
16 std::vector<int> v(count);
17
18 auto generator = tpf::chrono_random::random_generator<int>(0, 100);
19
21
22 std::set<std::string> threads;
23
25 auto endl = tpf::endl;
26
28
29 auto callback = [member = int{}, &output, &endl, &threads, &mutex](auto& v)
30 {
31 std::stringstream os;
32 os << std::this_thread::get_id() << " - &member: " << &member ;
33 threads.insert(os.str());
34
35 std::lock_guard<std::mutex> lock(mutex);
36 std::cout << "Thread ID: " << std::this_thread::get_id() << " - \t" << &member << std::endl;
37 };
38
39 Tpf_GoParallel_VoidAlgorithm_VoidCallback(for_each, callback,
40 std::execution::par, v.begin(), v.end());
41
42 stream << "Threads used: " << threads.size() << endl;
43
44 stream << threads << endl;
45
46}
47
48template<typename Type>
49struct functor
50{
51 inline static thread_local int m_thread_local;
52
53 inline static std::mutex m_mutex;
54
56
57 std::set<std::string>& threads;
58
59 functor(std::set<std::string>& set_threads):
60 threads{set_threads}
61 {
62 // std::cout << "constructor called" << std::endl;
63 }
64
65 functor(const functor& lhs): threads{lhs.threads}
66 {
67 // std::cout << "Copy constructor called" << std::endl;
68 }
69
71 {
72 // std::cout << "Move constructor called" << std::endl;
73 }
74
75 void operator()(Type& e) const
76 {
77 std::stringstream os;
78 os << std::this_thread::get_id() << " - &m_instance_member: " << &m_instance_member;
79 threads.insert(os.str());
80
81 std::lock_guard<std::mutex> lock(functor::m_mutex);
82 std::cout << "Thread ID: " << std::this_thread::get_id()
83 << " - \t" << &functor::m_thread_local << std::endl;
84 }
85
87 {
88 // std::cout << "Destructor called" << std::endl;
89 }
90};
91
93{
94 size_t count = 100;
95 std::vector<int> v(count);
96
97 auto generator = tpf::chrono_random::random_generator<int>(0, 100);
98
100
101 std::set<std::string> threads;
102
104 auto endl = tpf::endl;
105
106 auto callback = [member=int{}, &output, &endl, &threads](auto& v)
107 {
108 std::stringstream os;
109 os << std::this_thread::get_id();
110 threads.insert(os.str());
111 };
112
113 std::for_each(std::execution::par_unseq, v.begin(), v.end(), functor<int>{threads});
114
115 stream << "Threads used: " << threads.size() << endl;
116
117 stream << threads << endl;
118
119}
120
121
123{
124 size_t count = 100;
125 std::vector<int> v(count);
126
127 auto generator = tpf::chrono_random::random_generator<int>(0, 100);
128
130
131 auto callback = [](auto& e)
132 {
133 ++e;
134 };
135
136 stream << "Before: " << v << endl;
137
138 auto operation = tpf::parallel::safe_for_each(callback, std::execution::par_unseq, v.begin(), v.end());
139
140 if(operation)
141 stream << "After: " << v << endl;
142 else
143 stream <<"Operation failed" << endl;
144}
145
147{
148 size_t count = 100;
149 std::vector<int> v(count);
150
151 auto generator = tpf::chrono_random::random_generator<int>(0, 100);
152
154
155 auto callback = [](const auto& e)
156 {
157 return e + 1;
158 };
159
160 stream << "Before: " << v << endl;
161
162 auto operation =
163 tpf::parallel::safe_transform(callback, std::execution::par_unseq, v.begin(), v.end(), v.begin());
164
165 if(operation)
166 stream << "After: " << v << endl;
167 else
168 stream <<"Operation failed" << endl;
169}
170
172{
173 size_t count = 100;
174 std::vector<int> v(count);
175
176 auto generator = tpf::chrono_random::random_generator<int>(0, 100);
177
179
180 auto callback = [](auto& e)
181 {
182 ++e;
183 };
184
185 stream << "Before: " << v << endl;
186
187 try
188 {
189 tpf::parallel::throw_for_each(callback, std::execution::par_unseq, v.begin(), v.end());
190
191 stream << "After: " << v << endl;
192 }
193 catch(const std::exception& e)
194 {
195 stream << e << endl;
196 }
197
198}
199
201{
202 size_t count = 100;
203 using element_t = double;
204
205 std::vector<element_t> v(count);
206
207 auto generator = tpf::chrono_random::random_generator<element_t>(-10, 10);
208
210
212
213 auto callback = [&mutex, &generator](const auto& e)
214 {
215 std::lock_guard<std::mutex> lock(mutex);
216 auto d = generator();
217
218 return tpf::safe_type::safe_div(e, d);
219 };
220
221 stream << "Before: " << v << endl;
222
223 try
224 {
225 tpf::parallel::throw_transform(callback, std::execution::par_unseq, v.begin(), v.end(), v.begin());
226 stream << "After: " << v << endl;
227 }
228 catch(const std::exception& e)
229 {
230 stream << "Operation failed" << endl;
231 }
232
233}
234
235
237{
238 size_t count = 100;
239 using element_t = int;
240
241 std::vector<element_t> v(count);
242
243 auto generator = tpf::chrono_random::random_generator<element_t>(-10, 10);
244
246
248
249 auto callback = [](const auto& e)
250 {
251 return e % 5 == 0;
252 };
253
254 stream << "Before: " << v << endl;
255
256 auto [opr, rlt] = tpf::parallel::safe_find_if(callback, std::execution::par_unseq, v.begin(), v.end());
257
258 if(opr)
259 {
260 stream <<"Found: " << *rlt << endl;
261 }
262 else
263 {
264 stream << "Operation failed" << endl;
265 }
266
267}
268
269
270int main()
271{
272 // how_many_threads();
274
275 // test_for_each();
276 // test_transform();
277
278 // test_for_each_throw();
279
280 // test_transform_throw();
281
282 // test_find_if();
283}
std::mutex mutex
Definition: 022-mutex.cpp:12
std::atomic< int > count
Definition: 022-mutex.cpp:10
void safe_for_each(Policy &&policy, IteratorBegin &&begin, IteratorEnd &&end, Callback &&callback)
auto & cout
tpf::sstream stream
void how_many_threads_with_functor()
void test_transform_throw()
void test_for_each_throw()
void test_for_each()
auto endl
void how_many_threads()
void test_transform()
void test_find_if()
int main()
void random_fill(ContainerType< Type, Types... > &container, const RandomGeneratorType< RType, RTypes... > &random_generator)
Stream output operators are defined.
Definition: tpf_output.hpp:58
types::enable_if_integral_t< Type > safe_div(Type a, Type b)
Safe division of integral types.
constexpr auto endl
Definition: tpf_output.hpp:973
std::set< std::string > & threads
functor(functor &&lhs)
int m_instance_member
functor(std::set< std::string > &set_threads)
static thread_local int m_thread_local
static std::mutex m_mutex
void operator()(Type &e) const
functor(const functor &lhs)
Stream output operators << are implemented.
This file implements safe arithmetic.