内核优化
This commit is contained in:
@@ -1,125 +0,0 @@
|
||||
#pragma once
|
||||
#define TF_VERSION 400100
|
||||
#define TF_MAJOR_VERSION TF_VERSION/100000
|
||||
#define TF_MINOR_VERSION TF_VERSION/100%1000
|
||||
#define TF_PATCH_VERSION TF_VERSION%100
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <future>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace tf {
|
||||
class Taskflow;
|
||||
class Task {
|
||||
public:
|
||||
Task() = default;
|
||||
Task& name(std::string name);
|
||||
template <class... Tasks>
|
||||
Task& precede(Tasks... tasks) {
|
||||
(precede_one(tasks), ...);
|
||||
return *this;
|
||||
}
|
||||
template <class... Tasks>
|
||||
Task& succeed(Tasks... tasks) {
|
||||
(tasks.precede(*this), ...);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
friend class Taskflow;
|
||||
Task(Taskflow* graph, std::size_t index) : graph_(graph), index_(index) {}
|
||||
void precede_one(Task task);
|
||||
Taskflow* graph_{};
|
||||
std::size_t index_{};
|
||||
};
|
||||
class Taskflow {
|
||||
public:
|
||||
struct Node {
|
||||
std::function<void()> work;
|
||||
Taskflow* module{};
|
||||
std::string name;
|
||||
std::vector<std::size_t> successors;
|
||||
};
|
||||
template <class Callable>
|
||||
Task emplace(Callable&& callable) {
|
||||
nodes_.push_back({std::function<void()>(std::forward<Callable>(callable)), nullptr, {}, {}});
|
||||
return Task(this, nodes_.size() - 1);
|
||||
}
|
||||
Task composed_of(Taskflow& module) {
|
||||
nodes_.push_back({{}, &module, {}, {}});
|
||||
return Task(this, nodes_.size() - 1);
|
||||
}
|
||||
private:
|
||||
friend class Task;
|
||||
friend class Executor;
|
||||
void run() {
|
||||
std::vector<std::size_t> indegrees(nodes_.size());
|
||||
for (const Node& node : nodes_) {
|
||||
for (std::size_t successor : node.successors) {
|
||||
++indegrees.at(successor);
|
||||
}
|
||||
}
|
||||
std::queue<std::size_t> ready;
|
||||
for (std::size_t index = 0; index < indegrees.size(); ++index) {
|
||||
if (indegrees[index] == 0) {
|
||||
ready.push(index);
|
||||
}
|
||||
}
|
||||
std::size_t completed{};
|
||||
while (!ready.empty()) {
|
||||
std::size_t index = ready.front();
|
||||
ready.pop();
|
||||
Node& node = nodes_[index];
|
||||
if (node.module) {
|
||||
node.module->run();
|
||||
} else if (node.work) {
|
||||
node.work();
|
||||
}
|
||||
++completed;
|
||||
for (std::size_t successor : node.successors) {
|
||||
if (--indegrees.at(successor) == 0) {
|
||||
ready.push(successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (completed != nodes_.size()) {
|
||||
throw std::logic_error("taskflow cycle");
|
||||
}
|
||||
}
|
||||
std::vector<Node> nodes_;
|
||||
};
|
||||
inline Task& Task::name(std::string name) {
|
||||
graph_->nodes_.at(index_).name = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
inline void Task::precede_one(Task task) {
|
||||
if (graph_ != task.graph_) {
|
||||
throw std::invalid_argument("taskflow task owner");
|
||||
}
|
||||
graph_->nodes_.at(index_).successors.push_back(task.index_);
|
||||
}
|
||||
class Future {
|
||||
public:
|
||||
explicit Future(std::future<void> future) : future_(std::move(future)) {}
|
||||
void wait() {
|
||||
future_.wait();
|
||||
}
|
||||
void get() {
|
||||
future_.get();
|
||||
}
|
||||
private:
|
||||
std::future<void> future_;
|
||||
};
|
||||
class Executor {
|
||||
public:
|
||||
Future run(Taskflow& graph) {
|
||||
return Future(std::async(std::launch::async, [&graph] {
|
||||
graph.run();
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user