Lumiera  0.pre.03
»edit your freedom«
thread-wrapper-test.cpp
Go to the documentation of this file.
1 /*
2  ThreadWrapper(Test) - starting threads and passing context
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
19 #include "lib/test/run.hpp"
20 #include "lib/thread.hpp"
21 #include "lib/iter-explorer.hpp"
24 
25 #include <atomic>
26 #include <chrono>
27 
28 using test::Test;
29 using lib::explore;
30 using std::atomic_uint;
31 using std::this_thread::yield;
32 using std::this_thread::sleep_for;
33 using std::chrono::microseconds;
34 
35 
36 namespace lib {
37 namespace test{
38 
39  namespace { // test parameters
40 
41  const uint NUM_THREADS = 200;
42  const uint REPETITIONS = 10;
43  }
44 
45 
46  /*******************************************************************/
53  class ThreadWrapper_test : public Test
54  {
55 
56  virtual void
57  run (Arg)
58  {
59  seedRand();
62  }
63 
64 
66  void
68  {
69  atomic_uint i{0};
70  Thread thread("counter", [&]{ ++i; }); // bind a λ and launch thread
71  while (thread) yield(); // ensure thread has finished and detached
72 
73  CHECK (i == 1); // verify the effect has taken place
74  }
75 
76 
89  void
91  {
92  struct TestThread
93  : Thread
94  {
95  using Thread::Thread;
96 
97  uint local{0};
98 
99  void
100  doIt (uint a, uint b)
101  {
102  uint sum = a + b;
103  sleep_for (microseconds{sum}); // Note: explicit random delay before local store
104  local = sum;
105  }
106  };
107 
108  // prepare Storage for these objects (not created yet)
109  lib::ScopedCollection<TestThread> threads{NUM_THREADS};
110 
111  size_t checkSum = 0;
112  size_t globalSum = 0;
113  auto launchThreads = [&]
114  {
115  for (uint i=1; i<=NUM_THREADS; ++i)
116  {
117  uint x = rani(1000);
118  globalSum += (i + x);
119  threads.emplace (&TestThread::doIt, i, x);
120  } // Note: bind to member function, copying arguments
121 
122  while (explore(threads).has_any())
123  yield(); // wait for all threads to have detached
124 
125  for (auto& t : threads)
126  {
127  CHECK (0 < t.local);
128  checkSum += t.local;
129  }
130  };
131 
132  double runTime = benchmarkTime (launchThreads, REPETITIONS);
133 
134  CHECK (checkSum == globalSum); // sum of precomputed random numbers matches sum from threads
135  CHECK (runTime < NUM_THREADS * 1000/2); // random sleep time should be > 500ms on average
136  }
137  };
138 
139 
140 
142  LAUNCHER (ThreadWrapper_test, "function common");
143 
144 
145 
146 }} // namespace lib::test
A fixed collection of non-copyable polymorphic objects.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
Definition: run.hpp:40
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
Functions to perform (multithreaded) timing measurement on a given functor.
Implementation namespace for support and library code.
Managing a collection of non-copyable polymorphic objects in compact storage.
double benchmarkTime(FUN const &invokeTestCode, const size_t repeatCnt=1)
Helper to invoke a functor or λ to observe its running time.
Abstract Base Class for all testcases.
Definition: run.hpp:53
Simplistic test class runner.
void seedRand()
draw a new random seed from a common nucleus, and re-seed the default-Gen.
Definition: suite.cpp:211
Convenience front-end to simplify and codify basic thread handling.
A thin convenience wrapper to simplify thread-handling.
Definition: thread.hpp:648
Building tree expanding and backtracking evaluations within hierarchical scopes.