From 7a5e694c3ffed12532ee2b97f99c4b56dbba4d02 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 29 Mar 2018 10:56:18 +0200 Subject: WIP: more variant task --- src/server/CompiledGraph.cpp | 6 +-- src/server/CompiledGraph.hpp | 4 +- src/server/Task.cpp | 87 ++++++++++++++++++++------------- src/server/Task.hpp | 112 ++++++++++--------------------------------- 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(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(_master.get())->emplace_front(std::move(par)); + boost::get(_master).emplace_front(std::move(par)); blocks = std::move(predecessors); } @@ -195,7 +195,7 @@ MPtr 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 _master; + Task _master; }; MPtr 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 -simplify(std::unique_ptr&& task) +static bool empty(Task& task) { -#if 0 - if (boost::get(task.get())) { - return std::move(task); + if (SeqTask* seq = boost::get(&task)) { + return seq->children.empty(); + } else if (ParTask* par = boost::get(&task)) { + return par->children.empty(); } - std::unique_ptr ret = std::unique_ptr(new Task(task->mode())); - for (auto&& c : task->_children) { + return false; +} + +template +static Task +simplify(T&& task) +{ + typename std::remove_reference::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(&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(&task)) { + return simplify(std::move(*seq)); + } else if (ParTask* par = boost::get(&task)) { + return simplify(std::move(*par)); } - return ret; -#endif - return nullptr; + + return std::move(task); } -#if 0 void -Task::dump(std::function sink, unsigned indent, bool first) const +dump(Task& task, std::function sink, unsigned indent, bool first) { if (!first) { sink("\n"); @@ -153,17 +167,22 @@ Task::dump(std::function 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(&task)) { + sink(single->block->path()); + } else if (SeqTask* seq = boost::get(&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(&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; -using TaskChildren = std::deque>; +using TaskChildren = std::deque; +/** 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 void emplace_front(Args... args) { - children.emplace_front(new Task(std::forward(args)...)); + children.emplace_front(std::forward(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 next{0}; ///< Index of next sub-task - std::atomic 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 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 simplify(std::unique_ptr&& 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 - void emplace_front(Args... args) { - _children.emplace_front(std::unique_ptr(new Task(std::forward(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> Children; - - Task(const Task&) = delete; - Task& operator=(const Task&) = delete; - - Task* get_task(RunContext& context); - - void append(std::unique_ptr&& 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 _next; ///< Index of next sub-task - std::atomic _done; ///< Completion phase + unsigned done_end{0}; ///< Index of rightmost done sub-task + std::atomic next{0}; ///< Index of next sub-task + std::atomic done{false}; ///< Completion phase }; -#endif +struct Job { + Task task; +}; +/** Run task in the given context. */ void run(Task& task, RunContext& context); -std::unique_ptr simplify(std::unique_ptr&& 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 sink, unsigned indent, bool first); + } // namespace Server } // namespace Ingen -- cgit v1.2.1