summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/server/CompiledGraph.cpp6
-rw-r--r--src/server/CompiledGraph.hpp4
-rw-r--r--src/server/Task.cpp87
-rw-r--r--src/server/Task.hpp112
4 files changed, 83 insertions, 126 deletions
diff --git a/src/server/CompiledGraph.cpp b/src/server/CompiledGraph.cpp
index fbc7ab26..12867d2c 100644
--- a/src/server/CompiledGraph.cpp
+++ b/src/server/CompiledGraph.cpp
@@ -153,7 +153,7 @@ compile_block(BlockImpl* n, ParTask& task, BlockSet& k)
}
CompiledGraph::CompiledGraph(GraphImpl& graph)
- : _master(std::unique_ptr<Task>(new Task(SeqTask())))
+ : _master(SeqTask())
{
ThreadManager::assert_thread(THREAD_PRE_PROCESS);
@@ -179,7 +179,7 @@ CompiledGraph::CompiledGraph(GraphImpl& graph)
compile_block(b, par, predecessors);
}
- boost::get<SeqTask>(_master.get())->emplace_front(std::move(par));
+ boost::get<SeqTask>(_master).emplace_front(std::move(par));
blocks = std::move(predecessors);
}
@@ -195,7 +195,7 @@ MPtr<CompiledGraph> compile(Raul::Maid& maid, GraphImpl& graph)
Log& log = graph.engine().log();
auto sink = [&log](const std::string& s) { log.trace(s); };
sink(graph.path() + " =>\n ");
- //result->master().dump(sink, 2, true);
+ dump(result->master(), sink, 2, true);
sink("\n");
}
diff --git a/src/server/CompiledGraph.hpp b/src/server/CompiledGraph.hpp
index c3bb1ce1..552a0c35 100644
--- a/src/server/CompiledGraph.hpp
+++ b/src/server/CompiledGraph.hpp
@@ -44,10 +44,10 @@ class CompiledGraph : public Raul::Maid::Disposable
public:
explicit CompiledGraph(GraphImpl& graph);
- Task& master() { return *_master; }
+ Task& master() { return _master; }
private:
- std::unique_ptr<Task> _master;
+ Task _master;
};
MPtr<CompiledGraph> compile(Raul::Maid& maid, GraphImpl& graph);
diff --git a/src/server/Task.cpp b/src/server/Task.cpp
index 0978e15d..497f7895 100644
--- a/src/server/Task.cpp
+++ b/src/server/Task.cpp
@@ -33,9 +33,9 @@ get_task(ParTask& task, RunContext& context)
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;
- // }
+ 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
@@ -63,8 +63,8 @@ struct Runner
}
void operator()(SeqTask& task) {
- for (const auto& child : task.children) {
- run(*child, context);
+ for (auto& child : task.children) {
+ run(child, context);
}
}
@@ -104,47 +104,61 @@ steal(ParTask& task, RunContext& context)
{
const unsigned i = task.next++;
if (i < task.children.size()) {
- return task.children[i].get();
+ return &task.children[i];
}
return nullptr;
}
-std::unique_ptr<Task>
-simplify(std::unique_ptr<Task>&& task)
+static bool empty(Task& task)
{
-#if 0
- if (boost::get<SingleTask>(task.get())) {
- return std::move(task);
+ if (SeqTask* seq = boost::get<SeqTask>(&task)) {
+ return seq->children.empty();
+ } else if (ParTask* par = boost::get<ParTask>(&task)) {
+ return par->children.empty();
}
- std::unique_ptr<Task> ret = std::unique_ptr<Task>(new Task(task->mode()));
- for (auto&& c : task->_children) {
+ return false;
+}
+
+template<typename T>
+static Task
+simplify(T&& task)
+{
+ typename std::remove_reference<T>::type ret;
+ for (auto&& c : task.children) {
auto child = simplify(std::move(c));
- if (!child->empty()) {
- if (child->mode() == task->mode()) {
- // Merge child into parent
- for (auto&& grandchild : child->_children) {
- ret->append(std::move(grandchild));
+ if (!empty(child)) {
+ if (T* merge_child = boost::get<T>(&child)) {
+ // Child has same type, merge into parent
+ for (auto&& grandchild : merge_child->children) {
+ ret.children.emplace_back(std::move(grandchild));
}
} else {
- // Add child task
- ret->append(std::move(child));
+ // Append child task
+ ret.children.emplace_back(std::move(child));
}
}
}
- if (ret->_children.size() == 1) {
- return std::move(ret->_children.front());
+ return ret.children.size() == 1 ? std::move(ret.children.front())
+ : Task(std::move(ret));
+}
+
+Task
+simplify(Task&& task)
+{
+ if (SeqTask* seq = boost::get<SeqTask>(&task)) {
+ return simplify<SeqTask>(std::move(*seq));
+ } else if (ParTask* par = boost::get<ParTask>(&task)) {
+ return simplify<ParTask>(std::move(*par));
}
- return ret;
-#endif
- return nullptr;
+
+ return std::move(task);
}
-#if 0
void
-Task::dump(std::function<void (const std::string&)> sink, unsigned indent, bool first) const
+dump(Task& task, std::function<void (const std::string&)> sink, unsigned indent, bool first)
{
if (!first) {
sink("\n");
@@ -153,17 +167,22 @@ Task::dump(std::function<void (const std::string&)> sink, unsigned indent, bool
}
}
- if (_mode == Mode::SINGLE) {
- sink(_block->path());
- } else {
- sink(((_mode == Mode::SEQUENTIAL) ? "(seq " : "(par "));
- for (size_t i = 0; i < _children.size(); ++i) {
- _children[i]->dump(sink, indent + 5, i == 0);
+ if (SingleTask* single = boost::get<SingleTask>(&task)) {
+ sink(single->block->path());
+ } else if (SeqTask* seq = boost::get<SeqTask>(&task)) {
+ sink("(seq ");
+ for (size_t i = 0; i < seq->children.size(); ++i) {
+ dump(seq->children[i], sink, indent + 5, i == 0);
+ }
+ sink(")");
+ } else if (ParTask* par = boost::get<ParTask>(&task)) {
+ sink("(par ");
+ for (size_t i = 0; i < par->children.size(); ++i) {
+ dump(par->children[i], sink, indent + 5, i == 0);
}
sink(")");
}
}
-#endif
} // namespace Server
} // namespace Ingen
diff --git a/src/server/Task.hpp b/src/server/Task.hpp
index 25f76260..79ada9f0 100644
--- a/src/server/Task.hpp
+++ b/src/server/Task.hpp
@@ -39,25 +39,29 @@ struct ParTask;
using Task = boost::variant<SingleTask, SeqTask, ParTask>;
-using TaskChildren = std::deque<std::unique_ptr<Task>>;
+using TaskChildren = std::deque<Task>;
+/** A basic task that contains a single node. */
struct SingleTask {
BlockImpl* block; ///< Block to run
};
+/** Base for tasks that contain multiple children. */
struct MultiTask {
/** Prepend a child to this task. */
template<typename... Args>
void emplace_front(Args... args) {
- children.emplace_front(new Task(std::forward<Args>(args)...));
+ children.emplace_front(std::forward<Args>(args)...);
}
TaskChildren children; ///< Child tasks
};
+/** A task with children that must be run sequentially in order. */
struct SeqTask : MultiTask {
};
+/** A task with children that can be run in any order in parallel. */
struct ParTask : MultiTask {
ParTask() = default;
@@ -65,105 +69,39 @@ struct ParTask : MultiTask {
: done_end(task.done_end)
, next(task.next.load())
, done(task.done.load())
- {}
-
- unsigned done_end{0}; ///< Index of rightmost done sub-task
- std::atomic<unsigned> next{0}; ///< Index of next sub-task
- std::atomic<bool> done{false}; ///< Completion phase
-};
-
- #if 0
-class Task {
-public:
- enum class Mode {
- SINGLE, ///< Single block to run
- SEQUENTIAL, ///< Elements must be run sequentially in order
- PARALLEL ///< Elements may be run in any order in parallel
- };
-
- explicit Task(BlockImpl* block)
- : _block(block)
- , _mode(Mode::SINGLE)
- , _done_end(0)
- , _next(0)
- , _done(false)
- {
- assert(block);
- assert(!(_mode == Mode::SINGLE && !_block));
- }
-
-
- Task(Mode mode)
- : _block(nullptr)
- , _mode(mode)
- , _done_end(0)
- , _next(0)
- , _done(false)
{
- assert(!(_mode == Mode::SINGLE && !_block));
- }
-
- /** Run task in the given context. */
- void run(RunContext& context);
-
- /** Pretty print task to the given stream (recursively). */
- void dump(std::function<void (const std::string&)> sink, unsigned indent, bool first) const;
-
- /** Return true iff this is an empty task. */
- bool empty() const { return _mode != Mode::SINGLE && _children.empty(); }
-
- /** Simplify task expression. */
- static std::unique_ptr<Task> simplify(std::unique_ptr<Task>&& task);
-
- /** Steal a child task from this task (succeeds for PARALLEL only). */
- Task* steal(RunContext& context);
-
- /** Return the child task at the front of this task. */
- Task& front() const {
- return *_children.front();
- }
-
- /** Prepend a child to this task. */
- template<typename... Args>
- void emplace_front(Args... args) {
- _children.emplace_front(std::unique_ptr<Task>(new Task(std::forward<Args>(args)...)));
+ children = std::move(task.children);
}
- Mode mode() const { return _mode; }
- BlockImpl* block() const { return _block; }
- bool done() const { return _done; }
-
- void set_done(bool done) { _done = done; }
-
-private:
- typedef std::deque<std::unique_ptr<Task>> Children;
-
- Task(const Task&) = delete;
- Task& operator=(const Task&) = delete;
-
- Task* get_task(RunContext& context);
-
- void append(std::unique_ptr<Task>&& t) {
- _children.emplace_back(std::move(t));
+ ParTask& operator=(ParTask&& task) {
+ children = std::move(task.children);
+ done_end = task.done_end;
+ next = task.next.load();
+ done = task.done.load();
+ return *this;
}
- Children _children; ///< Vector of child tasks
- BlockImpl* _block; ///< Used for SINGLE only
- Mode _mode; ///< Execution mode
- unsigned _done_end; ///< Index of rightmost done sub-task
- std::atomic<unsigned> _next; ///< Index of next sub-task
- std::atomic<bool> _done; ///< Completion phase
+ unsigned done_end{0}; ///< Index of rightmost done sub-task
+ std::atomic<unsigned> next{0}; ///< Index of next sub-task
+ std::atomic<bool> done{false}; ///< Completion phase
};
-#endif
+struct Job {
+ Task task;
+};
+/** Run task in the given context. */
void run(Task& task, RunContext& context);
-std::unique_ptr<Task> simplify(std::unique_ptr<Task>&& task);
+/** Simplify and optimize task. */
+Task simplify(Task&& task);
/** Steal a child task from this task. */
Task* steal(ParTask& task, RunContext& context);
+/** Pretty print task to the given stream (recursively). */
+void dump(Task& task, std::function<void (const std::string&)> sink, unsigned indent, bool first);
+
} // namespace Server
} // namespace Ingen