From bfc4a60a092a8c9c254b2c1fbc282cc21cfc22f1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 29 Sep 2023 17:46:24 +0200 Subject: [PATCH] Library: rework ThreadWrapper_test ...while the change in the thread-wrapper implementation was drop-in, this test in the existing from is questionable: it actually tests locking --- tests/library/sync-locking-test_2.cpp | 147 ++++++++++++++++++++++++++ tests/library/thread-wrapper-test.cpp | 86 +++++---------- wiki/thinkPad.ichthyo.mm | 70 ++++++++---- 3 files changed, 228 insertions(+), 75 deletions(-) create mode 100644 tests/library/sync-locking-test_2.cpp diff --git a/tests/library/sync-locking-test_2.cpp b/tests/library/sync-locking-test_2.cpp new file mode 100644 index 000000000..298af6450 --- /dev/null +++ b/tests/library/sync-locking-test_2.cpp @@ -0,0 +1,147 @@ +/* + SyncLocking(Test) - check the monitor object based locking + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + +/** @file sync-locking-test.cpp + ** unit test \ref SyncLocking_test + */ + + +#include "lib/test/run.hpp" + +#include "lib/thread.hpp" +#include "lib/sync.hpp" +#include "lib/symbol.hpp" + +#include + +using std::bind; +using test::Test; + + +namespace lib { + namespace test { + + namespace { // private test classes and data... + + const uint NUM_THREADS = 20; + const uint MAX_RAND_SUMMAND = 100; + + + class Checker + : public lib::Sync<> + { + volatile ulong hot_sum_; + ulong control_sum_; + + public: + Checker() : hot_sum_(0), control_sum_(0) { } + + bool + verify() ///< verify test values got handled and accounted + { + return 0 < hot_sum_ + && control_sum_ == hot_sum_; + } + + uint + createVal() ///< generating test values, remembering the control sum + { + uint val(rand() % MAX_RAND_SUMMAND); + control_sum_ += val; + return val; + } + + void + addValues (uint a, uint b) ///< to be called concurrently + { + Lock guard(this); + + hot_sum_ *= 2; + usleep (200); // force preemption + hot_sum_ += 2 * (a+b); + usleep (200); + hot_sum_ /= 2; + } + }; + + + Checker checksum; ///< global variable used by multiple threads + + + + + struct TestThread + : Thread + { + TestThread() + : Thread{&TestThread::theOperation, checksum.createVal(), checksum.createVal()} + { } // note the binding (functor object) is passed as anonymous temporary + + + void + theOperation (uint a, uint b) ///< the actual operation running in a separate thread + { + checksum.addValues (a,b); + } + }; + + } // (End) test classes and data.... + + + + + + + + + + + /**********************************************************************//** + * @test use the Lumiera Vault to create some new threads, utilising the + * lumiera::Thread wrapper for binding to an arbitrary operation + * and passing the appropriate context. + * + * @see vault::Thread + * @see threads.h + */ + class SyncLocking_test2 : public Test + { + + virtual void + run (Arg) + { + TestThread instances[NUM_THREADS] SIDEEFFECT; + + usleep (200000); // pause 200ms for the threads to terminate..... + + CHECK (checksum.verify()); + } + }; + + + + /** Register this test class... */ + LAUNCHER (SyncLocking_test2, "function common"); + + + +}} // namespace lib::test diff --git a/tests/library/thread-wrapper-test.cpp b/tests/library/thread-wrapper-test.cpp index 4738526d6..00d4ead0c 100644 --- a/tests/library/thread-wrapper-test.cpp +++ b/tests/library/thread-wrapper-test.cpp @@ -26,15 +26,14 @@ #include "lib/test/run.hpp" - #include "lib/thread.hpp" -#include "lib/sync.hpp" -#include "lib/symbol.hpp" +#include "lib/scoped-collection.hpp" -#include +#include -using std::bind; using test::Test; +using std::this_thread::sleep_for; +using std::chrono::microseconds; namespace lib { @@ -42,65 +41,22 @@ namespace lib { namespace { // private test classes and data... - const uint NUM_THREADS = 20; - const uint MAX_RAND_SUMMAND = 100; - - - class Checker - : public lib::Sync<> - { - volatile ulong hot_sum_; - ulong control_sum_; - - public: - Checker() : hot_sum_(0), control_sum_(0) { } - - bool - verify() ///< verify test values got handled and accounted - { - return 0 < hot_sum_ - && control_sum_ == hot_sum_; - } - - uint - createVal() ///< generating test values, remembering the control sum - { - uint val(rand() % MAX_RAND_SUMMAND); - control_sum_ += val; - return val; - } - - void - addValues (uint a, uint b) ///< to be called concurrently - { - Lock guard(this); - - hot_sum_ *= 2; - usleep (200); // force preemption - hot_sum_ += 2 * (a+b); - usleep (200); - hot_sum_ /= 2; - } - }; - - - Checker checksum; ///< global variable used by multiple threads - - + const uint NUM_THREADS = 200; struct TestThread : Thread { - TestThread() - : Thread{&TestThread::theOperation, checksum.createVal(), checksum.createVal()} - { } // note the binding (functor object) is passed as anonymous temporary + using Thread::Thread; + uint local{0}; void - theOperation (uint a, uint b) ///< the actual operation running in a separate thread + doIt (uint a, uint b) ///< the actual operation running in a separate thread { - checksum.addValues (a,b); + uint sum = a + b; + sleep_for (microseconds{sum}); + local = sum; } }; @@ -129,11 +85,27 @@ namespace lib { virtual void run (Arg) { - TestThread instances[NUM_THREADS] SIDEEFFECT; + lib::ScopedCollection threads{NUM_THREADS}; + + size_t globalSum = 0; + for (uint i=1; i<=NUM_THREADS; ++i) + { + uint x = rand() % 1000; + globalSum += (i + x); + threads.emplace (&TestThread::doIt, uint{i}, uint{x}); + } usleep (200000); // pause 200ms for the threads to terminate..... - CHECK (checksum.verify()); + size_t checkSum = 0; + for (auto& t : threads) + { + CHECK (not t); + CHECK (0 < t.local); + checkSum += t.local; + } + CHECK (checkSum == globalSum); + } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2059bb43a..3d30d1bcd 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -79268,7 +79268,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79329,15 +79329,15 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - + @@ -79350,7 +79350,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79375,17 +79375,40 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + + +

+ es wurde von Race-Problemen berichtet, und davon, daß der zuletzt gesetzte Identifier plötzlich auf allen Threads auftaucht +

+ +
+
- - - + + + + + + + + + + + @@ -79486,7 +79509,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79912,7 +79935,7 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + @@ -79928,8 +79951,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -79948,11 +79971,22 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + - - + + + + + + +

+ ...indem man testet, daß eine bestimmte Berechnung stattgefunden hat +

+ + +
+