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) Lumiera.org
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/sync-barrier.hpp"
30 #include "lib/iter-explorer.hpp"
31 #include "lib/thread.hpp"
32 
33 #include <chrono>
34 #include <atomic>
35 #include <array>
36 
37 using test::Test;
38 using lib::explore;
39 using std::array;
40 
41 using std::atomic_uint;
42 using std::this_thread::sleep_for;
43 using namespace std::chrono_literals;
44 
45 
46 namespace lib {
47 namespace test {
48 
49  namespace {// Test setup for a concurrent calculation with checksum....
50 
51  const uint NUM_THREADS = 256;
52 
53  atomic_uint stage1{0};
54  atomic_uint stage2{0};
55  atomic_uint finish{0};
56 
57  SyncBarrier interThread{NUM_THREADS };
58  SyncBarrier afterThread{NUM_THREADS+1};
59 
66  class TestThread
67  : public lib::Thread
68  {
69  public:
70  TestThread()
71  : Thread{"Load Test"
72  ,[&]()
73  { //-STAGE-1------------------------------
74  localSum = rand() % 1000; // generate local value
75  stage1.fetch_add (localSum); // book in local value
76  interThread.sync(); // wait for all other threads to have booked in
77 
78  //-STAGE-2------------------------------
79  uint sync = stage1; // pick up compounded sum from STAGE-1
80  localSum += rand() % 1000; // add further local value for STAGE-2
81  stage2.fetch_add (localSum+sync); // book in both local values and synced sum
82  afterThread.sync(); // wait for other threads and supervisor
83 
84  finish.fetch_add(1); // mark completion of this thread
85  }}
86  { }
87 
88  uint localSum; // *deliberately* not initialised to avoid race
89  };
90 
91 
93  template<class CON>
94  uint
95  sumLocals (CON const& threads)
96  {
97  return explore (threads)
98  .reduce ([&](TestThread const& t){ return t.localSum; });
99  }
100  }//(End)Test setup
101 
102 
103 
104 
105  /*******************************************************************/
114  class SyncBarrier_test : public Test
115  {
116 
117  virtual void
118  run (Arg)
119  {
120  array<TestThread,NUM_THREADS> threads;
121 
122  CHECK (0 == finish);
123  CHECK (explore(threads).and_all());
124 
125  afterThread.sync();
126  sleep_for (5ms); // give the threads a chance to terminate
127 
128  CHECK (NUM_THREADS == finish); // all threads have passed out....
129  CHECK (0 < stage1);
130  CHECK (stage1 < stage2);
131  CHECK (stage2 > sumLocals(threads));
132  CHECK (stage2 == sumLocals(threads) + NUM_THREADS*stage1); // this holds only if all threads waited to get the complete stage1 sum
133  }
134  };
135 
136 
137 
139  LAUNCHER (SyncBarrier_test, "function common");
140 
141 
142 
143 }} // 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:49
Implementation namespace for support and library code.
Abstract Base Class for all testcases.
Definition: run.hpp:62
Simple 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:656
Building tree expanding and backtracking evaluations within hierarchical scopes.
A N-fold synchronisation latch using yield-wait until fulfilment.