summaryrefslogtreecommitdiffstats
path: root/src/server/CompiledGraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/CompiledGraph.cpp')
-rw-r--r--src/server/CompiledGraph.cpp163
1 files changed, 93 insertions, 70 deletions
diff --git a/src/server/CompiledGraph.cpp b/src/server/CompiledGraph.cpp
index 0d51f284..e4af74ba 100644
--- a/src/server/CompiledGraph.cpp
+++ b/src/server/CompiledGraph.cpp
@@ -15,6 +15,7 @@
*/
#include <algorithm>
+#include <set>
#include "ingen/ColorContext.hpp"
#include "ingen/Configuration.hpp"
@@ -23,11 +24,14 @@
#include "CompiledGraph.hpp"
#include "Engine.hpp"
#include "GraphImpl.hpp"
-#include "ThreadManager.hpp"
namespace Ingen {
namespace Server {
+typedef std::set<BlockImpl*> BlockSet;
+typedef Task BlockTask;
+typedef Work<BlockImpl> IR;
+
/** Graph contains ambiguous feedback with no delay nodes. */
class FeedbackException : public std::exception {
public:
@@ -52,30 +56,6 @@ has_provider_with_many_dependants(BlockImpl* n)
return false;
}
-CompiledGraph::CompiledGraph(GraphImpl* graph)
- : _master(Task::Mode::SEQUENTIAL)
-{
- compile_graph(graph);
-}
-
-MPtr<CompiledGraph>
-CompiledGraph::compile(Raul::Maid& maid, GraphImpl& graph)
-{
- try {
- return maid.make_managed<CompiledGraph>(&graph);
- } catch (FeedbackException e) {
- Log& log = graph.engine().log();
- if (e.node && e.root) {
- log.error(fmt("Feedback compiling %1% from %2%\n")
- % e.node->path() % e.root->path());
- } else {
- log.error(fmt("Feedback compiling %1%\n")
- % e.node->path());
- }
- return MPtr<CompiledGraph>();
- }
-}
-
static size_t
num_unvisited_dependants(BlockImpl* block)
{
@@ -103,11 +83,15 @@ parallel_depth(BlockImpl* block)
return 2 + min_provider_depth;
}
-void
-CompiledGraph::compile_graph(GraphImpl* graph)
-{
- ThreadManager::assert_thread(THREAD_PRE_PROCESS);
+static void
+compile_block(BlockImpl* n,
+ IR& task,
+ size_t max_depth,
+ std::set<BlockImpl*>& k);
+static BlockTask
+compile_graph(GraphImpl* graph)
+{
// Start with sink nodes (no outputs, or connected only to graph outputs)
std::set<BlockImpl*> blocks;
for (auto& b : graph->blocks()) {
@@ -120,6 +104,8 @@ CompiledGraph::compile_graph(GraphImpl* graph)
}
}
+ IR main = IR::sequential();
+
// Keep compiling working set until all nodes are visited
while (!blocks.empty()) {
std::set<BlockImpl*> predecessors;
@@ -130,26 +116,21 @@ CompiledGraph::compile_graph(GraphImpl* graph)
depth = std::min(depth, parallel_depth(i));
}
- Task par(Task::Mode::PARALLEL);
+ IR par = IR::parallel();
for (auto b : blocks) {
assert(num_unvisited_dependants(b) == 0);
- Task seq(Task::Mode::SEQUENTIAL);
+ IR seq = IR::sequential();
compile_block(b, seq, depth, predecessors);
- par.push_front(std::move(seq));
+ par.prepend(std::move(seq));
}
- _master.push_front(std::move(par));
+ main.prepend(std::move(par));
blocks = predecessors;
}
- _master = Task::simplify(std::move(_master));
-
- if (graph->engine().world()->conf().option("trace").get<int32_t>()) {
- ColorContext ctx(stderr, ColorContext::Color::YELLOW);
- dump(graph->path());
- }
+ return BlockTask::compile(main);
}
-/** Throw a FeedbackException iff `dependant` has `root` as a dependency. */
+/** Throw a FeedbackException iff `provider` has `root` as a dependency. */
static void
check_feedback(const BlockImpl* root, BlockImpl* provider)
{
@@ -173,12 +154,12 @@ check_feedback(const BlockImpl* root, BlockImpl* provider)
}
}
-void
-CompiledGraph::compile_provider(const BlockImpl* root,
- BlockImpl* block,
- Task& task,
- size_t max_depth,
- std::set<BlockImpl*>& k)
+static void
+compile_provider(const BlockImpl* root,
+ BlockImpl* block,
+ IR& task,
+ size_t max_depth,
+ std::set<BlockImpl*>& k)
{
if (block->dependants().size() > 1) {
/* Provider has other dependants, so this is the tail of a sequential task.
@@ -189,11 +170,11 @@ CompiledGraph::compile_provider(const BlockImpl* root,
}
} else if (max_depth > 0) {
// Calling dependant has only this provider, add here
- if (task.mode() == Task::Mode::PARALLEL) {
+ if (task.mode() == IR::Mode::PARALLEL) {
// Inside a parallel task, compile into a new sequential child
- Task seq(Task::Mode::SEQUENTIAL);
+ IR seq = IR::sequential();
compile_block(block, seq, max_depth, k);
- task.push_front(std::move(seq));
+ task.prepend(std::move(seq));
} else {
// Prepend to given sequential task
compile_block(block, task, max_depth, k);
@@ -205,18 +186,18 @@ CompiledGraph::compile_provider(const BlockImpl* root,
}
}
-void
-CompiledGraph::compile_block(BlockImpl* n,
- Task& task,
- size_t max_depth,
- std::set<BlockImpl*>& k)
+static void
+compile_block(BlockImpl* n,
+ IR& task,
+ size_t max_depth,
+ std::set<BlockImpl*>& k)
{
switch (n->get_mark()) {
case BlockImpl::Mark::UNVISITED:
n->set_mark(BlockImpl::Mark::VISITING);
// Execute this task after the providers to follow
- task.push_front(Task(Task::Mode::SINGLE, n));
+ task.prepend(IR::unit(*n));
if (n->providers().size() < 2) {
// Single provider, prepend it to this sequential task
@@ -233,11 +214,11 @@ CompiledGraph::compile_block(BlockImpl* n,
} else {
// Multiple providers with only this node as dependant,
// make a new parallel task to execute them
- Task par(Task::Mode::PARALLEL);
+ IR par = IR::parallel();
for (auto p : n->providers()) {
compile_provider(n, p, par, max_depth - 1, k);
}
- task.push_front(std::move(par));
+ task.prepend(std::move(par));
}
n->set_mark(BlockImpl::Mark::VISITED);
break;
@@ -250,23 +231,65 @@ CompiledGraph::compile_block(BlockImpl* n,
}
}
-void
-CompiledGraph::run(RunContext& context)
+static void
+dump_string(const std::string& str)
{
- _master.run(context);
+ fwrite(str.c_str(), 1, str.size(), stderr);
}
-void
-CompiledGraph::dump(const std::string& name) const
+static void
+dump_task(const BlockTask& task, unsigned indent, bool first)
+{
+ if (!first) {
+ dump_string("\n");
+ for (unsigned i = 0; i < indent; ++i) {
+ dump_string(" ");
+ }
+ }
+
+ if (task.mode() == BlockTask::Mode::UNIT) {
+ dump_string(task.unit()->path());
+ } else {
+ dump_string((task.mode() == BlockTask::Mode::SEQUENTIAL)
+ ? "(seq "
+ : "(par ");
+ for (size_t i = 0; i < task.children().size(); ++i) {
+ dump_task(task.children()[i], indent + 5, i == 0);
+ }
+ dump_string(")");
+ }
+}
+
+static void
+dump(const BlockTask& task, const std::string& name)
+{
+ dump_string("(compiled-graph ");
+ dump_string(name);
+ dump_task(task, 2, false);
+ dump_string(")\n");
+}
+
+MPtr<CompiledGraph>
+compile(Raul::Maid& maid, GraphImpl& graph)
{
- auto sink = [](const std::string& s) {
- fwrite(s.c_str(), 1, s.size(), stderr);
- };
-
- sink("(compiled-graph ");
- sink(name);
- _master.dump(sink, 2, false);
- sink(")\n");
+ try {
+ BlockTask master(compile_graph(&graph));
+ if (graph.engine().world()->conf().option("trace").get<int32_t>()) {
+ ColorContext ctx(stderr, ColorContext::Color::YELLOW);
+ dump(master, graph.path());
+ }
+ return maid.make_managed<CompiledGraph>(std::move(master));
+ } catch (FeedbackException e) {
+ Log& log = graph.engine().log();
+ if (e.node && e.root) {
+ log.error(fmt("Feedback compiling %1% from %2%\n")
+ % e.node->path() % e.root->path());
+ } else {
+ log.error(fmt("Feedback compiling %1%\n")
+ % e.node->path());
+ }
+ return MPtr<CompiledGraph>();
+ }
}
} // namespace Server