diff options
Diffstat (limited to 'src/server/Task.cpp')
-rw-r--r-- | src/server/Task.cpp | 67 |
1 files changed, 32 insertions, 35 deletions
diff --git a/src/server/Task.cpp b/src/server/Task.cpp index 497f7895..48a82085 100644 --- a/src/server/Task.cpp +++ b/src/server/Task.cpp @@ -19,31 +19,25 @@ #include <boost/variant/get.hpp> +#include <xmmintrin.h> + namespace Ingen { namespace Server { -static Task* -get_task(ParTask& task, RunContext& context) +static Job +get_job(ParTask& task, RunContext& context) { // Attempt to "steal" a task from ourselves - Task* t = steal(task, context); - if (t) { - return t; + Job job = steal(task, context); + if (job.task) { + return job; } - while (true) { - // Push done end index as forward as possible - while (task.done_end < task.children.size() && task.children[task.done_end].done()) { - ++task.done_end; - } - - if (task.done_end >= task.children.size()) { - return nullptr; // All child tasks are finished - } - + while (task.done < task.children.size()) { // All child tasks claimed, but some are unfinished, steal a task - if ((t = context.steal_task())) { - return t; + job = context.steal_task(); + if (job.task) { + return job; } /* All child tasks are claimed, and we failed to steal any tasks. Spin @@ -51,7 +45,10 @@ get_task(ParTask& task, RunContext& context) signal in non-main threads, and maybe even in the main thread depending on your real-time safe philosophy... more experimentation here is needed. */ + _mm_pause(); } + + return Job{nullptr, nullptr}; } struct Runner @@ -64,50 +61,50 @@ struct Runner void operator()(SeqTask& task) { for (auto& child : task.children) { - run(child, context); + Job job{&child, nullptr}; + run(job, context); } } void operator()(ParTask& task) { - // Initialize (not) done state of sub-tasks - // for (const auto& child : task.children) { - // child.done = false; - // } - // Grab the first sub-task - task.next = 0; - task.done_end = 0; - Task* t = steal(task, context); + task.next = 1; + task.done = 0; + Job job{&task.children[0], &task}; // Allow other threads to steal sub-tasks context.claim_task(&task); // Run available tasks until this task is finished - for (; t; t = get_task(task, context)) { - run(*t, context); + for (; job.task; job = get_job(task, context)) { + run(job, context); } context.claim_task(nullptr); } - RunContext context; + RunContext& context; + ParTask* parent; }; void -run(Task& task, RunContext& context) +run(Job& job, RunContext& context) { - Runner runner{context}; - boost::apply_visitor(runner, task); + Runner runner{context, job.parent}; + boost::apply_visitor(runner, *job.task); + if (job.parent) { + ++job.parent->done; + } } -Task* +Job steal(ParTask& task, RunContext& context) { const unsigned i = task.next++; if (i < task.children.size()) { - return &task.children[i]; + return Job{&task.children[i], &task}; } - return nullptr; + return Job{nullptr, nullptr}; } static bool empty(Task& task) |