Lumiera  0.pre.03
»edit your freedom«
sync-barrier-test.cpp
Go to the documentation of this file.
1 /*
2  SyncBarrier(Test) - verify yield-waiting synchronisation latch
3 
4  Copyright (C)
5  2023, 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/sync-barrier.hpp"
21 #include "lib/iter-explorer.hpp"
22 #include "lib/thread.hpp"
23 
24 #include <chrono>
25 #include <atomic>
26 #include <array>
27 
28 using test::Test;
29 using lib::explore;
30 using std::array;
31 
32 using std::atomic_uint;
33 using std::this_thread::sleep_for;
34 using namespace std::chrono_literals;
35 
36 
37 namespace lib {
38 namespace test {
39 
40  namespace {// Test setup for a concurrent calculation with checksum....
41 
42  const uint NUM_THREADS = 256;
43 
44  atomic_uint stage1{0};
45  atomic_uint stage2{0};
46  atomic_uint finish{0};
47 
48  SyncBarrier interThread{NUM_THREADS };
49  SyncBarrier afterThread{NUM_THREADS+1};
50 
57  class TestThread
58  : public lib::Thread
59  {
60  public:
61  TestThread()
62  : Thread{"Load Test"
63  ,[&, ran=lib::Random{seedFromDefaultGen()}]
64  () mutable
65  { //-STAGE-1------------------------------
66  localSum = ran.i(1000); // generate local value
67  stage1.fetch_add (localSum); // book in local value
68  interThread.sync(); // wait for all other threads to have booked in
69 
70  //-STAGE-2------------------------------
71  uint sync = stage1; // pick up compounded sum from STAGE-1
72  localSum += ran.i(1000); // add further local value for STAGE-2
73  stage2.fetch_add (localSum+sync); // book in both local values and synced sum
74  afterThread.sync(); // wait for other threads and supervisor
75 
76  finish.fetch_add(1); // mark completion of this thread
77  }}
78  { }
79 
80  uint localSum; // *deliberately* not initialised to avoid race
81  };
82 
83 
85  template<class CON>
86  uint
87  sumLocals (CON const& threads)
88  {
89  return explore (threads)
90  .reduce ([&](TestThread const& t){ return t.localSum; });
91  }
92  }//(End)Test setup
93 
94 
95 
96 
97  /*******************************************************************/
106  class SyncBarrier_test : public Test
107  {
108 
109  virtual void
110  run (Arg)
111  {
112  seedRand();
113  // Launch several TestThread
114  array<TestThread,NUM_THREADS> threads;
115 
116  CHECK (0 == finish);
117  CHECK (explore(threads).and_all());
118 
119  afterThread.sync();
120  sleep_for (5ms); // give the threads a chance to terminate
121 
122  CHECK (NUM_THREADS == finish); // all threads have passed out....
123  CHECK (0 < stage1);
124  CHECK (stage1 < stage2);
125  CHECK (stage2 > sumLocals(threads));
126  CHECK (stage2 == sumLocals(threads) + NUM_THREADS*stage1); // this holds only if all threads waited to get the complete stage1 sum
127  }
128  };
129 
130 
131 
133  LAUNCHER (SyncBarrier_test, "function common");
134 
135 
136 
137 }} // namespace lib::test
A test thread to perform a summation protocol including synchronisation points.
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
uint sumLocals(CON const &threads)
sum up all localSum fields from all TestThread instances in a container
Definition: run.hpp:40
Implementation namespace for support and library code.
SeedNucleus & seedFromDefaultGen()
draw seed another Generator from the default RandomSequencer
Definition: random.cpp:74
Abstract Base Class for all testcases.
Definition: run.hpp:53
Simplistic test class runner.
Convenience front-end to simplify and codify basic thread handling.
A one time N-fold mutual synchronisation barrier.
A thin convenience wrapper to simplify thread-handling.
Definition: thread.hpp:648
Building tree expanding and backtracking evaluations within hierarchical scopes.
A N-fold synchronisation latch using yield-wait until fulfilment.