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
This commit is contained in:
Fischlurch 2023-09-29 17:46:24 +02:00
parent 201672a0ad
commit bfc4a60a09
3 changed files with 228 additions and 75 deletions

View file

@ -0,0 +1,147 @@
/*
SyncLocking(Test) - check the monitor object based locking
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
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 <functional>
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

View file

@ -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 <functional>
#include <chrono>
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<TestThread> 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> (&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);
}
};

View file

@ -79268,7 +79268,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1695597011139" ID="ID_125138411" MODIFIED="1695859127749" TEXT="Kopie des bestehenden Thread-Wrappers umschreiben">
<linktarget COLOR="#6ebe5a" DESTINATION="ID_125138411" ENDARROW="Default" ENDINCLINATION="43;-18;" ID="Arrow_ID_195305087" SOURCE="ID_215388471" STARTARROW="None" STARTINCLINATION="-113;6;"/>
<icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695597146529" ID="ID_938038908" MODIFIED="1695651348752" TEXT="std::thread liefert fast alle Funktionalit&#xe4;t">
<node COLOR="#435e98" CREATED="1695597146529" ID="ID_938038908" MODIFIED="1695948178166" TEXT="std::thread liefert fast alle Funktionalit&#xe4;t">
<icon BUILTIN="idea"/>
<node COLOR="#435e98" CREATED="1695600626208" ID="ID_688465099" MODIFIED="1695602235450" TEXT="als Basisklasse sichtbar?">
<icon BUILTIN="help"/>
@ -79329,15 +79329,15 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
<node COLOR="#338800" CREATED="1695597148544" ID="ID_1135683799" MODIFIED="1695651329233" TEXT="die sync() / syncThread() -Barrier ersatzlos zur&#xfc;ckbauen">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1695597151336" ID="ID_854108015" MODIFIED="1695651323636" TEXT="Konstruktor-Syntax anpassen">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1695597151336" FOLDED="true" ID="ID_854108015" MODIFIED="1695948193281" TEXT="Konstruktor-Syntax anpassen">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1695606839044" ID="ID_1024366951" MODIFIED="1695607662788" TEXT="ausweiten auf std::invoke">
<icon BUILTIN="yes"/>
<node CREATED="1695606859838" ID="ID_1502075570" MODIFIED="1695606889162" TEXT="kann damit alles &#xbb;function-like&#xab; ausf&#xfc;hren (auch Member-Functions)">
<icon BUILTIN="idea"/>
</node>
</node>
<node COLOR="#338800" CREATED="1695606903540" ID="ID_1827438483" MODIFIED="1695859113052" TEXT="Textuelle Thread-Kennung setzen">
<node COLOR="#338800" CREATED="1695606903540" FOLDED="true" ID="ID_1827438483" MODIFIED="1695859113052" TEXT="Textuelle Thread-Kennung setzen">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1695606935311" ID="ID_1002758793" MODIFIED="1695688125602" TEXT="nimmt jetzt einen string...">
<richcontent TYPE="NOTE"><html>
@ -79350,7 +79350,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1695606971754" ID="ID_1204181207" MODIFIED="1695688121178" TEXT="kann man das per PTHREAD setzen?">
<node COLOR="#435e98" CREATED="1695606971754" ID="ID_1204181207" MODIFIED="1695948106014" TEXT="kann man das per PTHREAD setzen?">
<icon BUILTIN="help"/>
<node CREATED="1695685220762" ID="ID_850524224" MODIFIED="1695685236149" TEXT="die POSIX-L&#xf6;sung ist unklar"/>
<node CREATED="1695685236698" ID="ID_443970152" MODIFIED="1695685253886" TEXT="es gibt eine GNU-Erweiterung in der glibc">
@ -79375,17 +79375,40 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node CREATED="1695688094422" ID="ID_1651431673" MODIFIED="1695688112227" TEXT="verwende pthread_setname_np() aus der Glibc"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695688145491" ID="ID_295533997" MODIFIED="1695688177623" TEXT="pr&#xfc;fen: auch individuell?">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1695688145491" ID="ID_295533997" MODIFIED="1695948095403" TEXT="pr&#xfc;fen: auch individuell?">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1695688164064" ID="ID_421411220" MODIFIED="1695688173273" TEXT="Eclipse: sehe den Identifier">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1695948075335" ID="ID_1873157858" MODIFIED="1695948093811" TEXT="sehe auch variabel dekorierte IDs">
<icon BUILTIN="button_ok"/>
</node>
<node CREATED="1695948115970" ID="ID_1540583557" MODIFIED="1695948165115" TEXT="die mehrfach auf Stackoverflow berichteten Probleme sind also gefixt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
es wurde von Race-Problemen berichtet, und davon, da&#223; der zuletzt gesetzte Identifier pl&#246;tzlich auf allen Threads auftaucht
</p>
</body>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
</node>
</node>
<node CREATED="1695607699183" ID="ID_470294434" MODIFIED="1695607712099" TEXT="Ctor-Varianten">
<node CREATED="1695607713041" ID="ID_1988127528" MODIFIED="1695607720299" TEXT="ohne Thread-Kennung"/>
<node CREATED="1695607745859" ID="ID_1296792416" MODIFIED="1695915558180" TEXT="direkt mit einem Member-Fun-Ptr">
</node>
<node COLOR="#338800" CREATED="1695607699183" ID="ID_470294434" MODIFIED="1695948172946" TEXT="Ctor-Varianten">
<icon BUILTIN="button_ok"/>
<node COLOR="#5b280f" CREATED="1695607713041" ID="ID_1988127528" MODIFIED="1695947917413" TEXT="ohne Thread-Kennung">
<icon BUILTIN="button_cancel"/>
<node CREATED="1695947918452" ID="ID_1572774749" MODIFIED="1695947927175" TEXT="keine gute Idee"/>
<node CREATED="1695947927691" ID="ID_1741044845" MODIFIED="1695947938603" TEXT="Gefahr von overload-ambiguity">
<icon BUILTIN="stop-sign"/>
</node>
</node>
<node COLOR="#338800" CREATED="1695607745859" ID="ID_1296792416" MODIFIED="1695947904446" TEXT="direkt mit einem Member-Fun-Ptr">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
@ -79486,7 +79509,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1695597337839" ID="ID_1776858144" MODIFIED="1695859098234" TEXT="detach() / join-Differenzierung">
<node COLOR="#338800" CREATED="1695597337839" FOLDED="true" ID="ID_1776858144" MODIFIED="1695859098234" TEXT="detach() / join-Differenzierung">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1695647408544" ID="ID_805151848" MODIFIED="1695651308867" TEXT="isValid() bzw. bool-Check">
<icon BUILTIN="button_ok"/>
@ -79912,7 +79935,7 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
</node>
</node>
<node COLOR="#338800" CREATED="1695597475293" ID="ID_1100470933" MODIFIED="1695859224044" TEXT="Aufruf der Thread-Funktion">
<node COLOR="#338800" CREATED="1695597475293" FOLDED="true" ID="ID_1100470933" MODIFIED="1695859224044" TEXT="Aufruf der Thread-Funktion">
<icon BUILTIN="button_ok"/>
<node CREATED="1695859157169" ID="ID_1142804524" MODIFIED="1695859174014" TEXT="in die Policy verlagert">
<icon BUILTIN="idea"/>
@ -79928,8 +79951,8 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394205547" ID="ID_1719816317" MODIFIED="1695394259544" TEXT="Tests umstellen und modernisieren">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394270093" ID="ID_585437655" MODIFIED="1695394271819" TEXT="ThreadWrapper_test">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1695394270093" ID="ID_585437655" MODIFIED="1696002274251" TEXT="ThreadWrapper_test">
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1695911786871" ID="ID_1371513124" MODIFIED="1695911794232" TEXT="l&#xe4;uft nach Umstellung">
<icon BUILTIN="button_ok"/>
</node>
@ -79948,11 +79971,22 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</html></richcontent>
<arrowlink COLOR="#fedec1" DESTINATION="ID_1532807851" ENDARROW="Default" ENDINCLINATION="416;-16;" ID="Arrow_ID_1646166026" STARTARROW="None" STARTINCLINATION="479;36;"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394418004" ID="ID_1846217863" MODIFIED="1695394504468" TEXT="testen: ein Aufruf pro Thread hat stattgefunden">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1695394519627" ID="ID_776125132" MODIFIED="1696002223375" TEXT="testen: individuelle Argument&#xfc;bergabe">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394519627" ID="ID_776125132" MODIFIED="1695394528873" TEXT="testen: individuelle Argument&#xfc;bergabe">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1695394418004" ID="ID_1846217863" MODIFIED="1696002269162" TEXT="testen: ein Aufruf pro Thread hat stattgefunden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...indem man testet, da&#223; eine bestimmte Berechnung stattgefunden hat
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394665822" ID="ID_881973960" MODIFIED="1695394668399" TEXT="ThreadWrapperJoin_test">