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:
parent
201672a0ad
commit
bfc4a60a09
3 changed files with 228 additions and 75 deletions
147
tests/library/sync-locking-test_2.cpp
Normal file
147
tests/library/sync-locking-test_2.cpp
Normal 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
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -79268,7 +79268,7 @@ Date:   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ät">
|
||||
<node COLOR="#435e98" CREATED="1695597146529" ID="ID_938038908" MODIFIED="1695948178166" TEXT="std::thread liefert fast alle Funktionalitä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:   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ü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 »function-like« ausfü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:   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ö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:   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üfen: auch individuell?">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1695688145491" ID="ID_295533997" MODIFIED="1695948095403" TEXT="prü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ß der zuletzt gesetzte Identifier plö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:   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:   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:   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äuft nach Umstellung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -79948,11 +79971,22 @@ Date:   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übergabe">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1695394519627" ID="ID_776125132" MODIFIED="1695394528873" TEXT="testen: individuelle Argumentü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ß 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">
|
||||
|
|
|
|||
Loading…
Reference in a new issue