14 #ifndef hifi_task_Task_h
15 #define hifi_task_Task_h
20 #include <unordered_map>
25 template <
class JC,
class TP>
class JobT;
26 template <
class JC,
class TP>
class TaskT;
41 ~TaskFlow() =
default;
43 bool doAbortTask()
const;
46 bool _doAbortTask{
false };
58 virtual ~JobContext();
60 std::shared_ptr<JobConfig> jobConfig {
nullptr };
67 using JobContextPointer = std::shared_ptr<JobContext>;
72 using Config = JobConfig;
74 JobConcept(
const std::string& name, QConfigPointer config) : _config(config), _name(name) { config->_jobConcept =
this; }
75 virtual ~JobConcept() =
default;
77 const std::string& getName()
const {
return _name; }
79 virtual const Varying getInput()
const {
return Varying(); }
80 virtual const Varying getOutput()
const {
return Varying(); }
81 virtual Varying& editInput() = 0;
83 virtual QConfigPointer& getConfiguration() {
return _config; }
84 virtual void applyConfiguration() = 0;
85 void setCPURunTime(
const std::chrono::nanoseconds& runtime) { (_config)->setCPURunTime(runtime); }
87 QConfigPointer _config;
89 const std::string _name;
93 template <
class T,
class C>
void jobConfigure(T& data,
const C& configuration) {
94 data.configure(configuration);
96 template<
class T>
void jobConfigure(T&,
const JobConfig&) {
100 template <
class T,
class JC>
void jobRun(T& data,
const JC& jobContext,
const JobNoIO& input, JobNoIO& output) {
101 data.run(jobContext);
103 template <
class T,
class JC,
class I>
void jobRun(T& data,
const JC& jobContext,
const I& input, JobNoIO& output) {
104 data.run(jobContext, input);
106 template <
class T,
class JC,
class O>
void jobRun(T& data,
const JC& jobContext,
const JobNoIO& input, O& output) {
107 data.run(jobContext, output);
109 template <
class T,
class JC,
class I,
class O>
void jobRun(T& data,
const JC& jobContext,
const I& input, O& output) {
110 data.run(jobContext, input, output);
113 template <
class JC,
class TP>
117 using TimeProfiler = TP;
118 using ContextPointer = std::shared_ptr<Context>;
119 using Config = JobConfig;
120 using None = JobNoIO;
122 class Concept :
public JobConcept {
124 Concept(
const std::string& name, QConfigPointer config) : JobConcept(name, config) {}
125 virtual ~Concept() =
default;
127 virtual void run(
const ContextPointer& jobContext) = 0;
129 using ConceptPointer = std::shared_ptr<Concept>;
131 template <
class T,
class C = Config,
class I = None,
class O = None>
class Model :
public Concept {
141 const Varying getInput()
const override {
return _input; }
142 const Varying getOutput()
const override {
return _output; }
143 Varying& editInput()
override {
return _input; }
145 template <
class... A>
146 Model(
const std::string& name,
const Varying& input, QConfigPointer config, A&&... args) :
147 Concept(name, config),
148 _data(Data(std::forward<A>(args)...)),
150 _output(Output(), name +
".o") {
151 applyConfiguration();
154 template <
class... A>
155 static std::shared_ptr<Model> create(
const std::string& name,
const Varying& input, A&&... args) {
156 assert(input.canCast<I>());
157 return std::make_shared<Model>(name, input, std::make_shared<C>(), std::forward<A>(args)...);
160 void createConfiguration() {
162 auto config = std::make_shared<C>();
164 config->transferChildrenConfigs(Concept::_config);
166 Concept::_config = config;
168 Concept::_config->_jobConcept =
this;
171 void applyConfiguration()
override {
172 TimeProfiler probe((
"configure::" + JobConcept::getName()));
174 jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
177 void run(
const ContextPointer& jobContext)
override {
178 jobContext->jobConfig = std::static_pointer_cast<Config>(Concept::_config);
179 if (jobContext->jobConfig->isEnabled()) {
180 jobRun(_data, jobContext, _input.get<I>(), _output.edit<O>());
182 jobContext->jobConfig.reset();
187 template <
class T,
class I,
class O,
class C = Config>
using ModelIO =
Model<T, C, I, O>;
190 Job(
const ConceptPointer& conceptPtr) : _conceptPtr(conceptPtr) {}
191 virtual ~Job() =
default;
193 const std::string& getName()
const {
return _conceptPtr->getName(); }
194 const Varying getInput()
const {
return _conceptPtr->getInput(); }
195 const Varying getOutput()
const {
return _conceptPtr->getOutput(); }
197 QConfigPointer& getConfiguration()
const {
return _conceptPtr->getConfiguration(); }
198 void applyConfiguration() {
return _conceptPtr->applyConfiguration(); }
200 template <
class I>
void feedInput(
const I& in) { _conceptPtr->editInput().template edit<I>() = in; }
201 template <
class I,
class S>
void feedInput(
int index,
const S& inS) { (_conceptPtr->editInput().template editN<I>(index)).
template edit<S>() = inS; }
203 template <
class T> T& edit() {
204 auto conceptPtr = std::static_pointer_cast<typename T::JobModel>(_conceptPtr);
206 return conceptPtr->_data;
209 template <
class T>
const T& get()
const {
210 auto conceptPtr = std::static_pointer_cast<typename T::JobModel>(_conceptPtr);
212 return conceptPtr->_data;
215 virtual void run(
const ContextPointer& jobContext) {
216 TimeProfiler probe(getName());
217 auto startTime = std::chrono::high_resolution_clock::now();
218 _conceptPtr->run(jobContext);
219 _conceptPtr->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime));
223 ConceptPointer _conceptPtr;
234 template <
class JC,
class TP>
235 class Task :
public Job<JC, TP> {
238 using TimeProfiler = TP;
239 using ContextPointer = std::shared_ptr<Context>;
240 using Config = JobConfig;
241 using JobType = Job<JC, TP>;
242 using None =
typename JobType::None;
243 using Concept =
typename JobType::Concept;
244 using ConceptPointer =
typename JobType::ConceptPointer;
245 using Jobs = std::vector<JobType>;
247 Task(ConceptPointer conceptPtr) : JobType(conceptPtr) {}
249 class TaskConcept :
public Concept {
255 const Varying getInput()
const override {
return _input; }
256 const Varying getOutput()
const override {
return _output; }
257 Varying& editInput()
override {
return _input; }
259 TaskConcept(
const std::string& name,
const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {config->_isTask =
true;}
262 template <
class NT,
class... NA>
const Varying addJob(std::string name,
const Varying& input, NA&&... args) {
263 _jobs.emplace_back((NT::JobModel::create(name, input, std::forward<NA>(args)...)));
266 std::static_pointer_cast<JobConfig>(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name);
268 return _jobs.back().getOutput();
270 template <
class NT,
class... NA>
const Varying addJob(std::string name, NA&&... args) {
271 const auto input = Varying(
typename NT::JobModel::Input());
272 return addJob<NT>(name, input, std::forward<NA>(args)...);
276 template <
class T,
class C = Config,
class I = None,
class O = None>
class TaskModel :
public TaskConcept {
284 TaskModel(
const std::string& name,
const Varying& input, QConfigPointer config) :
285 TaskConcept(name, input, config),
288 template <
class... A>
289 static std::shared_ptr<TaskModel> create(
const std::string& name,
const Varying& input, A&&... args) {
290 auto model = std::make_shared<TaskModel>(name, input, std::make_shared<C>());
293 TimeProfiler probe(
"build::" + model->getName());
294 model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
300 template <
class... A>
301 static std::shared_ptr<TaskModel> create(
const std::string& name, A&&... args) {
302 const auto input = Varying(Input());
303 return create(name, input, std::forward<A>(args)...);
306 void createConfiguration() {
308 auto config = std::make_shared<C>();
310 config->transferChildrenConfigs(Concept::_config);
312 Concept::_config = config;
314 Concept::_config->_jobConcept =
this;
317 QConfigPointer& getConfiguration()
override {
318 if (!Concept::_config) {
319 createConfiguration();
321 return Concept::_config;
324 void applyConfiguration()
override {
325 TimeProfiler probe(
"configure::" + JobConcept::getName());
326 jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
327 for (
auto& job : TaskConcept::_jobs) {
328 job.applyConfiguration();
332 void run(
const ContextPointer& jobContext)
override {
333 auto config = std::static_pointer_cast<C>(Concept::_config);
334 if (config->isEnabled()) {
335 for (
auto job : TaskConcept::_jobs) {
337 if (jobContext->taskFlow.doAbortTask()) {
338 jobContext->taskFlow.reset();
345 template <
class T,
class C = Config>
using Model = TaskModel<T, C, None, None>;
346 template <
class T,
class I,
class C = Config>
using ModelI = TaskModel<T, C, I, None>;
347 template <
class T,
class O,
class C = Config>
using ModelO = TaskModel<T, C, None, O>;
348 template <
class T,
class I,
class O,
class C = Config>
using ModelIO = TaskModel<T, C, I, O>;
351 template <
class T,
class... A>
const Varying addJob(std::string name,
const Varying& input, A&&... args) {
352 return std::static_pointer_cast<TaskConcept>(JobType::_conceptPtr)->template addJob<T>(name, input, std::forward<A>(args)...);
354 template <
class T,
class... A>
const Varying addJob(std::string name, A&&... args) {
355 const auto input = Varying(
typename T::JobModel::Input());
356 return std::static_pointer_cast<TaskConcept>(JobType::_conceptPtr)->template addJob<T>(name, input, std::forward<A>(args)...);
359 std::shared_ptr<Config> getConfiguration() {
360 return std::static_pointer_cast<Config>(JobType::_conceptPtr->getConfiguration());
372 template <
class JC,
class TP>
373 class Switch :
public Job<JC, TP> {
376 using TimeProfiler = TP;
377 using ContextPointer = std::shared_ptr<Context>;
378 using Config = JobConfig;
379 using JobType = Job<JC, TP>;
380 using None =
typename JobType::None;
381 using Concept =
typename JobType::Concept;
382 using ConceptPointer =
typename JobType::ConceptPointer;
383 using Branches = std::unordered_map<uint8_t, JobType>;
385 Switch(ConceptPointer conceptPtr) : JobType(conceptPtr) {}
387 class SwitchConcept :
public Concept {
393 const Varying getInput()
const override {
return _input; }
394 const Varying getOutput()
const override {
return _output; }
395 Varying& editInput()
override {
return _input; }
397 SwitchConcept(
const std::string& name,
const Varying& input, QConfigPointer config) : Concept(name, config), _input(input)
398 {config->_isTask =
true; config->_isSwitch =
true; }
400 template <
class NT,
class... NA>
const Varying addBranch(std::string name, uint8_t index,
const Varying& input, NA&&... args) {
401 auto& branch = _branches[index];
402 branch = JobType(NT::JobModel::create(name, input, std::forward<NA>(args)...));
405 std::static_pointer_cast<JobConfig>(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name);
407 return branch.getOutput();
409 template <
class NT,
class... NA>
const Varying addBranch(std::string name, uint8_t index, NA&&... args) {
410 const auto input = Varying(
typename NT::JobModel::Input());
411 return addBranch<NT>(name, index, input, std::forward<NA>(args)...);
415 template <
class T,
class C = Config,
class I = None,
class O = None>
class SwitchModel :
public SwitchConcept {
423 SwitchModel(
const std::string& name,
const Varying& input, QConfigPointer config) :
424 SwitchConcept(name, input, config),
428 template <
class... A>
429 static std::shared_ptr<SwitchModel> create(
const std::string& name,
const Varying& input, A&&... args) {
430 auto model = std::make_shared<SwitchModel>(name, input, std::make_shared<C>());
433 TimeProfiler probe(
"build::" + model->getName());
434 model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
440 template <
class... A>
441 static std::shared_ptr<SwitchModel> create(
const std::string& name, A&&... args) {
442 const auto input = Varying(Input());
443 return create(name, input, std::forward<A>(args)...);
446 void createConfiguration() {
448 auto config = std::make_shared<C>();
450 config->transferChildrenConfigs(Concept::_config);
452 Concept::_config = config;
454 Concept::_config->_jobConcept =
this;
457 QConfigPointer& getConfiguration()
override {
458 if (!Concept::_config) {
459 createConfiguration();
461 return Concept::_config;
464 void applyConfiguration()
override {
465 TimeProfiler probe(
"configure::" + JobConcept::getName());
466 jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
467 for (
auto& branch : SwitchConcept::_branches) {
468 branch.second.applyConfiguration();
472 void run(
const ContextPointer& jobContext)
override {
473 auto config = std::static_pointer_cast<C>(Concept::_config);
474 if (config->isEnabled()) {
475 auto jobsIt = SwitchConcept::_branches.find(config->getBranch());
476 if (jobsIt != SwitchConcept::_branches.end()) {
477 jobsIt->second.run(jobContext);
482 template <
class T,
class C = Config>
using Model = SwitchModel<T, C, None, None>;
483 template <
class T,
class I,
class C = Config>
using ModelI = SwitchModel<T, C, I, None>;
489 template <
class T,
class... A>
const Varying addBranch(std::string name, uint8_t index,
const Varying& input, A&&... args) {
490 return std::static_pointer_cast<SwitchConcept>(JobType::_conceptPtr)->template addBranch<T>(name, index, input, std::forward<A>(args)...);
492 template <
class T,
class... A>
const Varying addBranch(std::string name, uint8_t index, A&&... args) {
493 const auto input = Varying(
typename T::JobModel::Input());
494 return std::static_pointer_cast<SwitchConcept>(JobType::_conceptPtr)->template addBranch<T>(name, index, input, std::forward<A>(args)...);
497 std::shared_ptr<Config> getConfiguration() {
498 return std::static_pointer_cast<Config>(JobType::_conceptPtr->getConfiguration());
502 template <
class JC,
class TP>
503 class Engine :
public Task<JC, TP> {
506 using ContextPointer = std::shared_ptr<Context>;
507 using Config = JobConfig;
509 using TaskType = Task<JC, TP>;
510 using ConceptPointer =
typename TaskType::ConceptPointer;
512 Engine(
const ConceptPointer& conceptPtr,
const ContextPointer& context) : TaskType(conceptPtr), _context(context) {}
515 void reset(
const ContextPointer& context) { _context = context; }
524 void run(
const ContextPointer& jobContext)
override {
525 TaskType::run(_context);
528 ContextPointer _context;
534 #define Task_DeclareTypeAliases(ContextType, TimeProfiler) \
535 using JobConfig = task::JobConfig; \
536 using TaskConfig = task::JobConfig; \
537 using SwitchConfig = task::JobConfig; \
538 template <class T> using PersistentConfig = task::PersistentConfig<T>; \
539 using Job = task::Job<ContextType, TimeProfiler>; \
540 using Switch = task::Switch<ContextType, TimeProfiler>; \
541 using Task = task::Task<ContextType, TimeProfiler>; \
542 using Engine = task::Engine<ContextType, TimeProfiler>; \
543 using Varying = task::Varying; \
544 template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2<T0, T1>; \
545 template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3<T0, T1, T2>; \
546 template < typename T0, typename T1, typename T2, typename T3 > using VaryingSet4 = task::VaryingSet4<T0, T1, T2, T3>; \
547 template < typename T0, typename T1, typename T2, typename T3, typename T4 > using VaryingSet5 = task::VaryingSet5<T0, T1, T2, T3, T4>; \
548 template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5 > using VaryingSet6 = task::VaryingSet6<T0, T1, T2, T3, T4, T5>; \
549 template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7<T0, T1, T2, T3, T4, T5, T6>; \
550 template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8<T0, T1, T2, T3, T4, T5, T6, T7>; \
551 template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > using VaryingSet9 = task::VaryingSet9<T0, T1, T2, T3, T4, T5, T6, T7, T8>; \
552 template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > using VaryingSet10 = task::VaryingSet10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>; \
553 template < class T, int NUM > using VaryingArray = task::VaryingArray<T, NUM>;
558 #include <PerfStat.h>
560 #define Task_DeclareCategoryTimeProfilerClass(className, category) \
561 class className : public PerformanceTimer { \
563 className(const std::string& label) : PerformanceTimer(label.c_str()), profileRange(category(), label.c_str()) {} \
564 ProfileDuration profileRange; \
A generic 3D model displaying geometry loaded from a URL.
Definition: Model.h:84