summaryrefslogtreecommitdiffstats
path: root/src/server/Task.cpp
diff options
context:
space:
mode:
authordrd <drd@ableton.com>2017-02-16 17:28:54 +0100
committerdrd <drd@ableton.com>2017-02-16 17:45:25 +0100
commite2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69 (patch)
treea57fe24b425ad37b3ce5cf32aefec99cee7ede12 /src/server/Task.cpp
parente29b2efa89ccfab0c631dae771b8c0e5b9616839 (diff)
downloadingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.tar.gz
ingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.tar.bz2
ingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.zip
Preliminary alternative parallel traversal/benchmarking work
Diffstat (limited to 'src/server/Task.cpp')
-rw-r--r--src/server/Task.cpp83
1 files changed, 48 insertions, 35 deletions
diff --git a/src/server/Task.cpp b/src/server/Task.cpp
index e19855d3..bf1f5028 100644
--- a/src/server/Task.cpp
+++ b/src/server/Task.cpp
@@ -1,6 +1,6 @@
/*
This file is part of Ingen.
- Copyright 2015-2016 David Robillard <http://drobilla.net/>
+ Copyright 2015-2017 David Robillard <http://drobilla.net/>
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
@@ -30,14 +30,14 @@ Task::run(RunContext& context)
_block->process(context);
break;
case Mode::SEQUENTIAL:
- for (Task& task : *this) {
- task.run(context);
+ for (const auto& task : _children) {
+ task->run(context);
}
break;
case Mode::PARALLEL:
// Initialize (not) done state of sub-tasks
- for (Task& task : *this) {
- task.set_done(false);
+ for (const auto& task : _children) {
+ task->set_done(false);
}
// Grab the first sub-task
@@ -65,12 +65,12 @@ Task::steal(RunContext& context)
{
if (_mode == Mode::PARALLEL) {
const unsigned i = _next++;
- if (i < size()) {
- return &(*this)[i];
+ if (i < _children.size()) {
+ return _children[i].get();
}
}
- return NULL;
+ return nullptr;
}
Task*
@@ -82,52 +82,65 @@ Task::get_task(RunContext& context)
return t;
}
+ int num_spins = 0;
while (true) {
// Push done end index as forward as possible
- for (; _done_end < size() && (*this)[_done_end].done(); ++_done_end) {}
+ while (_done_end < _children.size() && _children[_done_end]->done()) {
+ ++_done_end;
+ }
- if (_done_end >= size()) {
- return NULL; // All child tasks are finished
+ if (_done_end >= _children.size()) {
+ return nullptr; // All child tasks are finished
}
// All child tasks claimed, but some are unfinished, steal a task
- t = context.engine().steal_task(context.id() + 1);
- if (t) {
+ if ((t = context.engine().steal_task(context.id() + 1))) {
return t;
}
+ ++num_spins;
/* All child tasks are claimed, and we failed to steal any tasks. Spin
to prevent blocking, though it would probably be wiser to wait for a
signal in non-main threads, and maybe even in the main thread
depending on your real-time safe philosophy... more experimentation
here is needed. */
}
+
+ if (num_spins > 0) {
+ fprintf(stderr, "Num spins: %u\n", num_spins);
+ }
}
-void
-Task::simplify()
+std::unique_ptr<Task>
+Task::simplify(std::unique_ptr<Task>&& task)
{
- if (_mode != Mode::SINGLE) {
- for (std::vector<Task>::iterator t = begin(); t != end();) {
- t->simplify();
- if (t->mode() != Mode::SINGLE && t->empty()) {
- // Empty task, erase
- t = erase(t);
- } else if (t->mode() == _mode) {
- // Subtask with the same type, fold child into parent
- const Task child(*t);
- t = erase(t);
- t = insert(t, child.begin(), child.end());
- } else {
- ++t;
- }
- }
+ if (task->mode() == Mode::SINGLE) {
+ return std::move(task);
+ }
- if (size() == 1) {
- const Task t(front());
- *this = t;
+ for (auto t = task->_children.begin(); t != task->_children.end();) {
+ *t = simplify(std::move(*t));
+ if ((*t)->empty()) {
+ // Empty task, erase
+ t = task->_children.erase(t);
+ } else if ((*t)->mode() == task->_mode) {
+ // Subtask with the same type, fold child into parent
+ std::unique_ptr<Task> child(std::move(*t));
+ t = task->_children.erase(t);
+ t = task->_children.insert(
+ t,
+ std::make_move_iterator(child->_children.begin()),
+ std::make_move_iterator(child->_children.end()));
+ } else {
+ ++t;
}
}
+
+ if (task->_children.size() == 1) {
+ return std::move(task->_children.front());
+ }
+
+ return std::move(task);
}
void
@@ -144,8 +157,8 @@ Task::dump(std::function<void (const std::string&)> sink, unsigned indent, bool
sink(_block->path());
} else {
sink(((_mode == Mode::SEQUENTIAL) ? "(seq " : "(par "));
- for (size_t i = 0; i < size(); ++i) {
- (*this)[i].dump(sink, indent + 5, i == 0);
+ for (size_t i = 0; i < _children.size(); ++i) {
+ _children[i]->dump(sink, indent + 5, i == 0);
}
sink(")");
}