Workforce: draft simple usage

...start with an oversimplified implementation...
This commit is contained in:
Fischlurch 2023-09-04 23:48:12 +02:00
parent 70cd8af806
commit 38ab5a6aa9
5 changed files with 76 additions and 13 deletions

View file

@ -37,6 +37,7 @@
#include "vault/gear/work-force.hpp"
//#include "lib/symbol.hpp"
//#include "include/logging.h"
#include "lib/util.hpp"
//#include <string>
@ -49,12 +50,15 @@ namespace gear {
namespace { // internal details
size_t MINIMAL_CONCURRENCY = 2;
} // internal details
// NA::~NA() { }
const size_t WorkForce::FULL_SIZE = util::max (std::thread::hardware_concurrency(), MINIMAL_CONCURRENCY);

View file

@ -37,11 +37,17 @@
#include "vault/common.hpp"
#include "vault/gear/activity.hpp"
#include "lib/nocopy.hpp"
//#include "lib/symbol.hpp"
//#include "lib/util.hpp"
#include "lib/util.hpp"
//#include <string>
#include <functional>
#include <utility>
#include <vector>
#include <thread>
#include <atomic>
namespace vault{
@ -49,6 +55,8 @@ namespace gear {
// using util::isnil;
// using std::string;
using std::move;
using std::atomic;
/**
@ -60,27 +68,69 @@ namespace gear {
class WorkForce
: util::NonCopyable
{
short nothing_;
using WorkFun = std::function<activity::Proc(void)>;
using Pool = std::vector<std::thread>;
WorkFun workFun_;
Pool workers_;
atomic<bool> halt_{false};
public:
template<typename FUN>
static const size_t FULL_SIZE;
explicit
WorkForce (FUN&& fun)
: nothing_{42}
{ }
WorkForce (WorkFun&& fun)
: workFun_{move (fun)}
, workers_{}
{
workers_.reserve (1.5*FULL_SIZE);
}
~WorkForce()
{
try {
deactivate();
}
ERROR_LOG_AND_IGNORE (threadpool, "defunct worker thread")
}
void
activate (double degree =1.0)
{
UNIMPLEMENTED ("scale up");
halt_ = false;
size_t scale = util::max (size_t(degree*FULL_SIZE), 1u);
for (uint i = workers_.size(); i < scale; ++i)
workers_.emplace_back ([this]{ pullWork(); });
}
void
deactivate()
{
UNIMPLEMENTED ("scale down to halt");
halt_ = true;
for (auto& w : workers_)
if (w.joinable())
w.join();
workers_.clear();
}
private:
void
pullWork()
{
try {
while (true)
{
activity::Proc res = workFun_();
if (halt_ or res != activity::PASS)
break;
}
}
ERROR_LOG_AND_IGNORE (threadpool, "defunct worker thread")
}
};

View file

@ -28,7 +28,7 @@
#include "lib/test/run.hpp"
#include "vault/gear/work-force.hpp"
//#include "lib/time/timevalue.hpp"
//#include "lib/format-cout.hpp"
#include "lib/format-cout.hpp" ///////////////////////////////WIP
//#include "lib/util.hpp"
//#include <utility>
@ -75,9 +75,9 @@ namespace test {
void
simpleUsage()
{
uint check{0};
atomic<uint> check{0};
WorkForce wof{[&]{ ++check; return true; }};
WorkForce wof{[&]{ ++check; return activity::PASS; }};
CHECK (0 == check);

View file

@ -7167,14 +7167,14 @@ Later on we expect a distinct __query subsystem__ to emerge, presumably embeddin
&amp;rarr; QuantiserImpl</pre>
</div>
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202307272248" tags="Rendering spec draft" changecount="15">
<div title="Scheduler" creator="Ichthyostega" modifier="Ichthyostega" created="202304140131" modified="202309042142" tags="Rendering spec draft" changecount="17">
<pre>//Invoke and control the dependency and time based execution of [[render jobs|RenderJob]]//
The Scheduler acts as the central hub in the implementation of the RenderEngine and coordinates the //processing resources// of the application. Regarding architecture, the Scheduler is located in the Vault-Layer and //running// the Scheduler is equivalent to activating the »Vault Subsystem«. An EngineFaçade acts as entrance point, providing high-level render services to other parts of the application: [[render jobs|RenderJob]] can be activated under various timing and dependency constraints. Internally, the implementation is segregated into two layers
;Layer-2: Coordination
:maintains a network of interconnected [[activities|RenderActivity]], tracks dependencies and observes timing constraints
:coordinates a [[pool of active Workers|SchedulerWorker]] to dispatch the next activities
;Layer-1: Invocation
:operates a low-level priority scheduling mechanism for time-bound execution of [[activities|RenderActivity]]
:coordinates a ThreadPool and dispatches the execution of individual jobs into appropriate worker threads.
!Event based vs. time based operational control
Time bound delivery of media data is an important aspect of editing and playback -- yet other concerns are of similar importance: the ability to make optimum use of scarce resources and to complete extended processing in reasonable time, while retaining some overall responsiveness of the system. And, especially for the //final render,// it is tantamount to produce 100% correct results without any glitches -- a goal that can not be reconciled with the demand for perfect timing. These considerations alone are sufficient to indicate, that strict adherence to a pre-established calculation plan is not enough to build a viable render engine. As far as media processing is concerned, the limited I/O bandwidth is the most precious resource -- reading and writing data from persistent storage requires a lot of time, with generally unpredictable timings, necessitating asynchronous processing.

View file

@ -79627,6 +79627,15 @@ Date:&#160;&#160;&#160;Thu Apr 20 18:53:17 2023 +0200<br/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1693841488183" HGAP="-2" ID="ID_671611566" MODIFIED="1693841514321" TEXT="WorkForce_test (Komponententest)" VSHIFT="-3">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1693864786768" ID="ID_1997885802" MODIFIED="1693864791553" TEXT="simple usage">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1693864792879" ID="ID_1957135454" MODIFIED="1693864812713" TEXT="lediglich einen Pool hochfahren">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1693864804725" ID="ID_197610779" MODIFIED="1693864812213" TEXT="verifizieren da&#xdf; &#xfc;berhaupt etwas berechnet wird">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
</node>