37 std::vector<TopologyPolicy::DependencyChecker> dependencyCheckers;
38 dependencyCheckers.reserve(physicalWorkflow.size());
40 for (
auto& spec : physicalWorkflow) {
41 for (
auto& policy : topologyPolicies) {
42 if (policy.matcher(spec)) {
43 dependencyCheckers.push_back(policy.checkDependency);
48 assert(dependencyCheckers.size() == physicalWorkflow.size());
50 auto checkDependencies = [&workflow = physicalWorkflow,
51 &dependencyCheckers](
int i,
int j) {
53 return checker(workflow[
i], workflow[
j]);
55 std::vector<std::pair<int, int>> edges;
56 for (
size_t i = 0;
i < physicalWorkflow.size() - 1; ++
i) {
57 for (
size_t j =
i;
j < physicalWorkflow.size(); ++
j) {
58 if (
i ==
j && checkDependencies(
i,
j)) {
59 throw std::runtime_error(physicalWorkflow[
i].
name +
" depends on itself");
62 if (checkDependencies(
i,
j)) {
63 edges.emplace_back(
j,
i);
66 if (checkDependencies(
j,
i)) {
67 edges.emplace_back(
i,
j);
69 std::ostringstream
str;
70 describeDataProcessorSpec(
str, physicalWorkflow[
i]);
71 str <<
" has circular dependency with ";
72 describeDataProcessorSpec(
str, physicalWorkflow[
j]);
74 for (
auto x : {
i,
j}) {
75 str << physicalWorkflow[
x].name <<
":\n";
77 for (
auto& input : physicalWorkflow[
x].inputs) {
78 str <<
"- " << input <<
" " << (
int)input.lifetime <<
"\n";
81 for (
auto&
output : physicalWorkflow[
x].outputs) {
85 throw std::runtime_error(
str.str());