libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
thread_wrapper.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2010 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include <boost/mpl/list.hpp>
25 
26 #include "core/thread_wrapper.hpp"
27 
28 #include <typeinfo>
29 
30 using namespace libjmmcg;
31 
32 typedef boost::mpl::list<
33 // TODO ppd::sequential_mode,
36 
37 template<bool exit_val,class Mdl>
38 struct thread_wrapper final : public ppd::wrapper<ppd::platform_api, Mdl> {
40 
41  unsigned long i;
42 
43  __stdcall thread_wrapper() noexcept(true)
44  : base_t(),i(0) {
45  }
46  __stdcall ~thread_wrapper() noexcept(true) override {
47  this->exit_requested=true;
48  base_t::wait_thread_exit();
49  }
50 
51  bool __fastcall worker_fn(typename base_t::thread_context_t &) override {
52  ++i;
53  return exit_val;
54  }
55 };
56 
57 /**
58  \test Tests for the thread-as-a-class model.
59 */
60 BOOST_AUTO_TEST_SUITE(thread_wrapper_tests)
61 
62 BOOST_AUTO_TEST_SUITE(generic)
63 
64 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor, Mdl, thread_types) {
65  typedef thread_wrapper<true,Mdl> run_and_exit;
66 
67  run_and_exit thr;
68  BOOST_CHECK_EQUAL(thr.i,0U);
69 }
70 
71 BOOST_AUTO_TEST_CASE_TEMPLATE(start_thread, Mdl, thread_types) {
72  typedef thread_wrapper<true,Mdl> run_and_exit;
73 
74  run_and_exit thr;
75  BOOST_CHECK_EQUAL(thr.i,0U);
76  BOOST_CHECK_NO_THROW(thr.create_running());
77  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
78  BOOST_CHECK_GT(thr.i,0U);
79 }
80 
81 BOOST_AUTO_TEST_CASE_TEMPLATE(create_suspended, Mdl, thread_types) {
82  typedef thread_wrapper<true,Mdl> run_and_exit;
83 
84  run_and_exit thr;
85  BOOST_CHECK_EQUAL(thr.i,0U);
86 // TODO: Not on Pthreads: thr.create(run_and_exit::thread_traits::api_params_type::create_suspended);
87  BOOST_CHECK_EQUAL(thr.i,0U);
88 }
89 
90 BOOST_AUTO_TEST_CASE_TEMPLATE(create_suspended_thread_then_resume, Mdl, thread_types) {
91  typedef thread_wrapper<true,Mdl> run_and_exit;
92 
93  run_and_exit thr;
94  BOOST_CHECK_EQUAL(thr.i,0U);
95 // TODO: Not supported on Pthreads: thr.create(Thrds::thread_traits::api_params_type::create_suspended);
96  BOOST_CHECK_EQUAL(thr.i,0U);
97 // TODO: Not supported on Pthreads: thr.resume();
98  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
99 }
100 
101 BOOST_AUTO_TEST_CASE_TEMPLATE(create_running_thread_then_suspend, Mdl, thread_types) {
102  typedef thread_wrapper<true,Mdl> run_and_exit;
103 
104  run_and_exit thr;
105  BOOST_CHECK_EQUAL(thr.i,0U);
106  BOOST_CHECK_NO_THROW(thr.create_running());
107  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
108 // TODO: Not supported on Pthreads: thr.suspend();
109  BOOST_CHECK_GT(thr.i,0U);
110 }
111 
112 BOOST_AUTO_TEST_CASE_TEMPLATE(create_running_thread_then_suspend_then_resume, Mdl, thread_types) {
113  typedef thread_wrapper<true,Mdl> run_and_exit;
114 
115  run_and_exit thr;
116  BOOST_CHECK_EQUAL(thr.i,0U);
117  BOOST_CHECK_NO_THROW(thr.create_running());
118  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
119 // TODO: Not supported on Pthreads: thr.suspend();
120 // TODO: Not supported on Pthreads: thr.resume();
121  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
122  BOOST_CHECK_GT(thr.i,0U);
123 }
124 
125 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_two_threads, Mdl, thread_types) {
126  typedef thread_wrapper<true,Mdl> run_and_exit;
127 
128  run_and_exit thr1;
129  run_and_exit thr2;
130  BOOST_CHECK_EQUAL(thr1.i,0U);
131  BOOST_CHECK_EQUAL(thr2.i,0U);
132 }
133 
134 BOOST_AUTO_TEST_CASE_TEMPLATE(start_two_threads, Mdl, thread_types) {
135  typedef thread_wrapper<true,Mdl> run_and_exit;
136 
137  run_and_exit thr1;
138  run_and_exit thr2;
139  BOOST_CHECK_EQUAL(thr1.i,0U);
140  BOOST_CHECK_EQUAL(thr2.i,0U);
141  BOOST_CHECK_NO_THROW(thr1.create_running());
142  BOOST_CHECK_NO_THROW(thr2.create_running());
143  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
144  BOOST_CHECK_GT(thr1.i,0U);
145  BOOST_CHECK_GT(thr2.i,0U);
146 }
147 
148 BOOST_AUTO_TEST_CASE_TEMPLATE(start_two_suspended_threads, Mdl, thread_types) {
149  typedef thread_wrapper<true,Mdl> run_and_exit;
150 
151  run_and_exit thr1;
152  run_and_exit thr2;
153  BOOST_CHECK_EQUAL(thr1.i,0U);
154  BOOST_CHECK_EQUAL(thr2.i,0U);
155 // TODO: Not supported on Pthreads: thr1.create(Thrds::thread_traits::api_params_type::create_suspended);
156 // TODO: Not supported on Pthreads: thr2.create(Thrds::thread_traits::api_params_type::create_suspended);
157  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
158 }
159 
160 BOOST_AUTO_TEST_CASE_TEMPLATE(start_two_suspended_threads_then_resume_them, Mdl, thread_types) {
161  typedef thread_wrapper<true,Mdl> run_and_exit;
162 
163  run_and_exit thr1;
164  run_and_exit thr2;
165  BOOST_CHECK_EQUAL(thr1.i,0U);
166  BOOST_CHECK_EQUAL(thr2.i,0U);
167 // TODO: Not supported on Pthreads: thr1.create(Thrds::thread_traits::api_params_type::create_suspended);
168 // TODO: Not supported on Pthreads: thr2.create(Thrds::thread_traits::api_params_type::create_suspended);
169  BOOST_CHECK_EQUAL(thr1.i,0U);
170  BOOST_CHECK_EQUAL(thr2.i,0U);
171 // TODO: Not supported on Pthreads: thr1.resume();
172 // TODO: Not supported on Pthreads: thr2.resume();
173  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
174 }
175 
176 BOOST_AUTO_TEST_CASE_TEMPLATE(create_two_running_threads_then_suspend_them, Mdl, thread_types) {
177  typedef thread_wrapper<true,Mdl> run_and_exit;
178 
179  run_and_exit thr1;
180  run_and_exit thr2;
181  BOOST_CHECK_EQUAL(thr1.i,0U);
182  BOOST_CHECK_EQUAL(thr2.i,0U);
183  BOOST_CHECK_NO_THROW(thr1.create_running());
184  BOOST_CHECK_NO_THROW(thr2.create_running());
185  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
186 // TODO: Not supported on Pthreads: thr1.suspend();
187 // TODO: Not supported on Pthreads: thr2.suspend();
188  BOOST_CHECK_GT(thr1.i,0U);
189  BOOST_CHECK_GT(thr2.i,0U);
190 }
191 
192 BOOST_AUTO_TEST_CASE_TEMPLATE(create_two_running_threads_then_suspend_and_resume_them, Mdl, thread_types) {
193  typedef thread_wrapper<true,Mdl> run_and_exit;
194 
195  run_and_exit thr1;
196  run_and_exit thr2;
197  BOOST_CHECK_EQUAL(thr1.i,0U);
198  BOOST_CHECK_EQUAL(thr2.i,0U);
199  BOOST_CHECK_NO_THROW(thr1.create_running());
200  BOOST_CHECK_NO_THROW(thr2.create_running());
201  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
202 // TODO: Not supported on Pthreads: thr1.suspend();
203 // TODO: Not supported on Pthreads: thr2.suspend();
204 // TODO: Not supported on Pthreads: thr1.resume();
205 // TODO: Not supported on Pthreads: thr2.resume();
206  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
207 }
208 
209 BOOST_AUTO_TEST_SUITE_END()
210 
211 BOOST_AUTO_TEST_SUITE(stl_like)
212 
213 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_functor, Mdl, thread_types) {
214  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
215 
216  struct increment_ref {
217  std::atomic<unsigned int> &i_;
218 
219  explicit increment_ref(std::atomic<unsigned int> &i) noexcept(true)
220  : i_(i) {}
221 
222  void operator()() noexcept(true) {
223  ++i_;
224  }
225  };
226 
227  std::atomic<unsigned int> i{0U};
228  {
229  BOOST_CHECK_NO_THROW(run_and_exit thr{increment_ref(i)});
230  }
231  BOOST_CHECK_GE(i, 0U);
232  BOOST_CHECK_LE(i, 1U);
233 }
234 
235 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_stdbind, Mdl, thread_types) {
236  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
237 
238  struct increment_ref {
239  static void result(std::atomic<unsigned int> &i) noexcept(true) {
240  ++i;
241  }
242  };
243 
244  std::atomic<unsigned int> i{0U};
245  {
246  BOOST_CHECK_NO_THROW(run_and_exit thr(std::bind(&increment_ref::result, std::ref(i))));
247  }
248  BOOST_CHECK_GE(i, 0U);
249  BOOST_CHECK_LE(i, 1U);
250 }
251 
252 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_stdfn, Mdl, thread_types) {
253  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
254 
255  struct increment_ref {
256  void operator()(std::atomic<unsigned int> &i) noexcept(true) {
257  ++i;
258  }
259  };
260 
261  std::atomic<unsigned int> i{0U};
262  std::function<void ()> fn(std::bind(increment_ref(), std::ref(i)));
263  {
264  BOOST_CHECK_NO_THROW(run_and_exit thr(std::move(fn)));
265  }
266  BOOST_CHECK_GE(i, 0U);
267  BOOST_CHECK_LE(i, 1U);
268 }
269 
270 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_lambda, Mdl, thread_types) {
271  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
272 
273  std::atomic<unsigned int> i{0U};
274  {
275  BOOST_CHECK_NO_THROW(run_and_exit thr([&i]() {++i;}));
276  }
277  BOOST_CHECK_GE(i, 0U);
278  BOOST_CHECK_LE(i, 1U);
279 }
280 
281 BOOST_AUTO_TEST_CASE_TEMPLATE(create_suspended_thread_then_resume, Mdl, thread_types) {
282  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
283 
284  std::atomic<unsigned int> i{0U};
285  run_and_exit thr([&i]() {++i;});
286 // TODO: Not supported on Pthreads: thr.create(Thrds::thread_traits::api_params_type::create_suspended);
287  BOOST_CHECK_GE(i, 0U);
288  BOOST_CHECK_LE(i, 1U);
289 // TODO: Not supported on Pthreads: thr.resume();
290  ppd::api_threading_traits<ppd::platform_api,Mdl>::sleep(100);
291 }
292 
293 BOOST_AUTO_TEST_CASE_TEMPLATE(default_ctor_two_threads, Mdl, thread_types) {
294  using run_and_exit=ppd::thread<ppd::platform_api, Mdl>;
295 
296  std::atomic<unsigned int> i{0U};
297  {
298  BOOST_CHECK_NO_THROW(run_and_exit thr1([&i]() {++i;}));
299  BOOST_CHECK_NO_THROW(run_and_exit thr2([&i]() {++i;}));
300  }
301  BOOST_CHECK_GE(i, 0U);
302  BOOST_CHECK_LE(i, 2U);
303 }
304 
305 BOOST_AUTO_TEST_SUITE_END()
306 
307 BOOST_AUTO_TEST_SUITE(multi_threaded)
308 
309 BOOST_AUTO_TEST_CASE(default_ctor) {
310  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
311 
312  run_forever thr;
313  BOOST_CHECK_EQUAL(thr.i, 0U);
314 }
315 
316 BOOST_AUTO_TEST_CASE(start_thread) {
317  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
318 
319  run_forever thr;
320  BOOST_CHECK_EQUAL(thr.i, 0U);
321  BOOST_CHECK_NO_THROW(thr.create_running());
322  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
323  BOOST_CHECK_GT(thr.i,0U);
324 }
325 
326 BOOST_AUTO_TEST_CASE(create_suspended) {
327  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
328 
329  run_forever thr;
330  BOOST_CHECK_EQUAL(thr.i, 0U);
331  // TODO: Not on Pthreads: thr.create(run_and_exit::thread_traits::api_params_type::create_suspended);
332  BOOST_CHECK_EQUAL(thr.i, 0U);
333 }
334 
335 BOOST_AUTO_TEST_CASE(create_suspended_thread_then_resume) {
336  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
337 
338  run_forever thr;
339  BOOST_CHECK_EQUAL(thr.i, 0U);
340  // TODO: Not supported on Pthreads: thr.create(Thrds::thread_traits::api_params_type::create_suspended);
341  BOOST_CHECK_EQUAL(thr.i, 0U);
342  // TODO: Not supported on Pthreads: thr.resume();
343  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
344 }
345 
346 BOOST_AUTO_TEST_CASE(create_running_thread_then_suspend) {
347  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
348 
349  run_forever thr;
350  BOOST_CHECK_EQUAL(thr.i,0U);
351  BOOST_CHECK_NO_THROW(thr.create_running());
352  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
353  // TODO: Not supported on Pthreads: thr.suspend();
354 }
355 
356 BOOST_AUTO_TEST_CASE(create_running_thread_then_suspend_then_resume) {
357  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
358 
359  run_forever thr;
360  BOOST_CHECK_EQUAL(thr.i,0U);
361  BOOST_CHECK_NO_THROW(thr.create_running());
362  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
363  // TODO: Not supported on Pthreads: thr.suspend();
364  // TODO: Not supported on Pthreads: thr.resume();
365  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
366  BOOST_CHECK_GT(thr.i,0U);
367 }
368 
369 BOOST_AUTO_TEST_CASE(default_ctor_two_threads) {
370  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
371 
372  run_forever thr1;
373  run_forever thr2;
374  BOOST_CHECK_EQUAL(thr1.i,0U);
375  BOOST_CHECK_EQUAL(thr2.i,0U);
376 }
377 
378 BOOST_AUTO_TEST_CASE(start_two_threads) {
379  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
380 
381  run_forever thr1;
382  run_forever thr2;
383  BOOST_CHECK_EQUAL(thr1.i,0U);
384  BOOST_CHECK_EQUAL(thr2.i,0U);
385  BOOST_CHECK_NO_THROW(thr1.create_running());
386  BOOST_CHECK_NO_THROW(thr2.create_running());
387  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
388  BOOST_CHECK_GT(thr1.i,0U);
389  BOOST_CHECK_GT(thr2.i,0U);
390 }
391 
392 BOOST_AUTO_TEST_CASE(start_two_suspended_threads) {
393  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
394 
395  run_forever thr1;
396  run_forever thr2;
397  BOOST_CHECK_EQUAL(thr1.i,0U);
398  BOOST_CHECK_EQUAL(thr2.i,0U);
399  // TODO: Not supported on Pthreads: thr1.create(Thrds::thread_traits::api_params_type::create_suspended);
400  // TODO: Not supported on Pthreads: thr2.create(Thrds::thread_traits::api_params_type::create_suspended);
401  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
402 }
403 
404 BOOST_AUTO_TEST_CASE(start_two_suspended_threads_then_resume_them) {
405  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
406 
407  run_forever thr1;
408  run_forever thr2;
409  BOOST_CHECK_EQUAL(thr1.i,0U);
410  BOOST_CHECK_EQUAL(thr2.i,0U);
411  // TODO: Not supported on Pthreads: thr1.create(Thrds::thread_traits::api_params_type::create_suspended);
412  // TODO: Not supported on Pthreads: thr2.create(Thrds::thread_traits::api_params_type::create_suspended);
413  BOOST_CHECK_EQUAL(thr1.i,0U);
414  BOOST_CHECK_EQUAL(thr2.i,0U);
415  // TODO: Not supported on Pthreads: thr1.resume();
416  // TODO: Not supported on Pthreads: thr2.resume();
417  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
418 }
419 
420 BOOST_AUTO_TEST_CASE(create_two_running_threads_then_suspend_them) {
421  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
422 
423  run_forever thr1;
424  run_forever thr2;
425  BOOST_CHECK_EQUAL(thr1.i,0U);
426  BOOST_CHECK_EQUAL(thr2.i,0U);
427  BOOST_CHECK_NO_THROW(thr1.create_running());
428  BOOST_CHECK_NO_THROW(thr2.create_running());
429  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
430  // TODO: Not supported on Pthreads: thr1.suspend();
431  // TODO: Not supported on Pthreads: thr2.suspend();
432  BOOST_CHECK_GT(thr1.i,0U);
433  BOOST_CHECK_GT(thr2.i,0U);
434 }
435 
436 BOOST_AUTO_TEST_CASE(create_two_running_threads_then_suspend_and_resume_them) {
437  typedef thread_wrapper<false, ppd::heavyweight_threading> run_forever;
438 
439  run_forever thr1;
440  run_forever thr2;
441  BOOST_CHECK_EQUAL(thr1.i,0U);
442  BOOST_CHECK_EQUAL(thr2.i,0U);
443  BOOST_CHECK_NO_THROW(thr1.create_running());
444  BOOST_CHECK_NO_THROW(thr2.create_running());
445  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
446  // TODO: Not supported on Pthreads: thr1.suspend();
447  // TODO: Not supported on Pthreads: thr2.suspend();
448  // TODO: Not supported on Pthreads: thr1.resume();
449  // TODO: Not supported on Pthreads: thr2.resume();
450  ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>::sleep(100);
451  BOOST_CHECK_GT(thr1.i,0U);
452  BOOST_CHECK_GT(thr2.i,0U);
453 }
454 
455 BOOST_AUTO_TEST_SUITE_END()
456 
457 BOOST_AUTO_TEST_SUITE_END()