UI-Dispatch: get the multithreded test to work (#1098)
the (trivial) implementation turned out to be correct as written, but it was (again) damn challenging to get the mulithreaded chaotic test fixture and especially the lambda captures to work correct.
This commit is contained in:
parent
a7ad82c935
commit
46fc900980
3 changed files with 57 additions and 39 deletions
|
|
@ -51,7 +51,12 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "LifeCycle_test" LifeCycle_test <<END
|
||||
TEST "Dispatch functors into other threads" CallQueue_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "Application Lifecycle hooks" LifeCycle_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
@ -152,7 +157,7 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "Defining Suppport for specific timecode formats" FormatSupport_test <<END
|
||||
TEST "Suppport for specific timecode formats" FormatSupport_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -26,11 +26,10 @@
|
|||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/util.hpp"
|
||||
#include "lib/format-cout.hpp"
|
||||
#include "lib/scoped-collection.hpp"
|
||||
#include "backend/thread-wrapper.hpp"
|
||||
#include "lib/sync.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include "lib/call-queue.hpp"
|
||||
|
||||
|
|
@ -43,7 +42,6 @@ namespace lib {
|
|||
namespace test{
|
||||
|
||||
using lib::Sync;
|
||||
using backend::Thread;
|
||||
using backend::ThreadJoinable;
|
||||
|
||||
using util::isnil;
|
||||
|
|
@ -58,9 +56,9 @@ namespace test{
|
|||
uint const NUM_OF_THREADS = 50;
|
||||
uint const MAX_RAND_INCMT = 200;
|
||||
uint const MAX_RAND_STEPS = 500;
|
||||
uint const MAX_RAND_DELAY = 10000;
|
||||
uint const MAX_RAND_DELAY = 1000;
|
||||
// --------random-stress-test------
|
||||
|
||||
|
||||
|
||||
uint calc_sum = 0;
|
||||
uint ctor_sum = 0;
|
||||
|
|
@ -109,7 +107,7 @@ namespace test{
|
|||
*
|
||||
* @see lib::CallQueue
|
||||
* @see gui::NotificationService usage example
|
||||
* @see [DemoGuiRoundtrip]: http://issues.lumiera.org/ticket/1099 "Ticket #1099"
|
||||
* @see [DemoGuiRoundtrip](http://issues.lumiera.org/ticket/1099 "Ticket #1099")
|
||||
*/
|
||||
class CallQueue_test : public Test
|
||||
{
|
||||
|
|
@ -182,18 +180,34 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
using Step = std::function<uint()>;
|
||||
|
||||
struct Worker
|
||||
: ThreadJoinable
|
||||
, Sync<>
|
||||
{
|
||||
uint64_t localSum = 0;
|
||||
uint64_t producerSum = 0;
|
||||
uint64_t consumerSum = 0;
|
||||
|
||||
Worker(uint cnt, Step workStep)
|
||||
void
|
||||
countConsumerCall (uint increment)
|
||||
{
|
||||
Lock sync(this); // NOTE: will be invoked from some random other thread
|
||||
consumerSum += increment;
|
||||
}
|
||||
|
||||
Worker(CallQueue& queue)
|
||||
: ThreadJoinable{"CallQueue_test: concurrent dispatch"
|
||||
, [&]() {
|
||||
uint cnt = rand() % MAX_RAND_STEPS;
|
||||
uint delay = rand() % MAX_RAND_DELAY;
|
||||
|
||||
for (uint i=0; i<cnt; ++i)
|
||||
localSum += workStep();
|
||||
{
|
||||
uint increment = rand() % MAX_RAND_INCMT;
|
||||
queue.feed ([=]() { countConsumerCall(increment); });
|
||||
producerSum += increment;
|
||||
usleep (delay);
|
||||
queue.invoke(); // NOTE: dequeue one functor added during our sleep
|
||||
} // and thus belonging to some random other thread
|
||||
}}
|
||||
{ }
|
||||
};
|
||||
|
|
@ -201,43 +215,40 @@ namespace test{
|
|||
using Workers = lib::ScopedCollection<Worker>;
|
||||
|
||||
|
||||
/**
|
||||
* @test torture the CallQueue by massively multithreaded dispatch
|
||||
* - start #NUM_OF_THREADS (e.g. 50) threads in parallel
|
||||
* - each of those has a randomised execution pattern to
|
||||
* add new functors and dispatch other thread's functors
|
||||
*/
|
||||
void
|
||||
verify_ThreadSafety()
|
||||
{
|
||||
CallQueue queue;
|
||||
uint64_t globalSum = 0;
|
||||
uint64_t checkSum = 0;
|
||||
|
||||
Step step =[&]() -> uint
|
||||
{
|
||||
uint increment = rand() % MAX_RAND_INCMT;
|
||||
uint delay = rand() % MAX_RAND_DELAY;
|
||||
|
||||
queue.feed ([&]() { globalSum += increment; });
|
||||
usleep (delay);
|
||||
queue.invoke(); // NOTE: typically this dequeues some other entry added during our sleep
|
||||
return increment;
|
||||
};
|
||||
|
||||
uint const cntSteps = rand() % MAX_RAND_STEPS;
|
||||
|
||||
// Start a bunch of threads with random access pattern
|
||||
Workers workers{NUM_OF_THREADS,
|
||||
[&](Workers::ElementHolder& storage)
|
||||
{
|
||||
storage.create<Worker>(cntSteps, step);
|
||||
storage.create<Worker>(queue);
|
||||
}
|
||||
};
|
||||
|
||||
// wait for termination of all threads
|
||||
for (auto& worker : workers)
|
||||
worker.join();
|
||||
|
||||
// collect the results of all worker threads
|
||||
uint64_t globalProducerSum = 0;
|
||||
uint64_t globalConsumerSum = 0;
|
||||
for (auto& worker : workers)
|
||||
{
|
||||
worker.join();
|
||||
checkSum += worker.localSum;
|
||||
globalProducerSum += worker.producerSum;
|
||||
globalConsumerSum += worker.consumerSum;
|
||||
}
|
||||
|
||||
// VERIFY: locally recorded partial sums match total sum
|
||||
CHECK (globalSum == checkSum);
|
||||
CHECK (globalProducerSum == globalConsumerSum);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1501940591109" ID="ID_1925240675" MODIFIED="1501940773195" TEXT="#1099 DemoGuiRoundtrip">
|
||||
<arrowlink COLOR="#e5e53f" DESTINATION="ID_1007296291" ENDARROW="Default" ENDINCLINATION="-767;134;" ID="Arrow_ID_1440938291" STARTARROW="None" STARTINCLINATION="-51;592;"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1501940591109" ID="ID_1925240675" MODIFIED="1502075967876" TEXT="#1099 DemoGuiRoundtrip">
|
||||
<arrowlink COLOR="#e5e53f" DESTINATION="ID_1007296291" ENDARROW="Default" ENDINCLINATION="-931;34;" ID="Arrow_ID_1440938291" STARTARROW="None" STARTINCLINATION="-51;592;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1501940627280" ID="ID_1675066241" MODIFIED="1501940632019" TEXT="Dummy-Code im UI"/>
|
||||
<node CREATED="1501940632871" ID="ID_189611570" MODIFIED="1501940638539" TEXT="Dummy Proc-Command"/>
|
||||
|
|
@ -1047,18 +1047,20 @@
|
|||
</node>
|
||||
<node CREATED="1501939193031" HGAP="3" ID="ID_1045913810" MODIFIED="1501939200829" TEXT="Test" VSHIFT="20">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1501939204166" ID="ID_383444966" MODIFIED="1501946866881" TEXT="CallQueue_test">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1501939204166" ID="ID_383444966" MODIFIED="1502075950777" TEXT="CallQueue_test">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1501946847700" ID="ID_1917302142" MODIFIED="1501951434466" TEXT="basic">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1501946852555" ID="ID_1617455971" MODIFIED="1501951436667" TEXT="mehrere">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1501946856587" ID="ID_1780067399" MODIFIED="1501946862958" TEXT="Streß"/>
|
||||
<node COLOR="#338800" CREATED="1501946856587" ID="ID_1780067399" MODIFIED="1502075941722" TEXT="Streß">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1501939212693" ID="ID_1007296291" MODIFIED="1501940740143" TEXT="#1099 DemoGuiRoundtrip">
|
||||
<linktarget COLOR="#e5e53f" DESTINATION="ID_1007296291" ENDARROW="Default" ENDINCLINATION="-767;134;" ID="Arrow_ID_1440938291" SOURCE="ID_1925240675" STARTARROW="None" STARTINCLINATION="-51;592;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1501939212693" ID="ID_1007296291" MODIFIED="1502075967876" TEXT="#1099 DemoGuiRoundtrip">
|
||||
<linktarget COLOR="#e5e53f" DESTINATION="ID_1007296291" ENDARROW="Default" ENDINCLINATION="-931;34;" ID="Arrow_ID_1440938291" SOURCE="ID_1925240675" STARTARROW="None" STARTINCLINATION="-51;592;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1501939235834" ID="ID_1160414548" MODIFIED="1501939239653" TEXT="Menü-Eintrag"/>
|
||||
<node CREATED="1501939240217" ID="ID_325602880" MODIFIED="1501939252187" TEXT="triggert Proc-Command"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue