| 748 | } |
| 749 | |
| 750 | void setStepOrder(const std::vector<StepNum> &subStepList) { |
| 751 | std::unordered_set<StepNum> allSubSteps; |
| 752 | size_t j = 0; |
| 753 | for (auto &step : steps) { |
| 754 | for (size_t i = 0; i < step.stages.size(); i++) { |
| 755 | allSubSteps.insert({j, i}); |
| 756 | } |
| 757 | j++; |
| 758 | } |
| 759 | |
| 760 | // Make sure that subStepList includes every step once |
| 761 | for (const auto &stepNum : subStepList) { |
| 762 | auto it = allSubSteps.find(stepNum); |
| 763 | if (it != allSubSteps.end()) { |
| 764 | allSubSteps.erase(it); |
| 765 | } else { |
| 766 | throw std::runtime_error("Queue step order cannot include substep multiple times"); |
| 767 | } |
| 768 | } |
| 769 | |
| 770 | if (!allSubSteps.empty()) { |
| 771 | throw std::runtime_error("Queue step order list must include all defined steps"); |
| 772 | } |
| 773 | |
| 774 | QueueStage *prevStage = nullptr; |
| 775 | for (const auto &stepNum : subStepList) { |
| 776 | auto &stage = steps[stepNum.threadNum].stages[stepNum.subStepNum]; |
| 777 | stage->stepNum = stepNum; |
| 778 | if (prevStage != nullptr) { |
| 779 | stage->linkBack(*prevStage); |
| 780 | } else { |
| 781 | stage->prevDone = &importDone; |
| 782 | } |
| 783 | prevStage = stage.get(); |
| 784 | } |
| 785 | |
| 786 | auto lastStepNum = subStepList.back(); |
| 787 | auto &lastStage = steps[lastStepNum.threadNum].stages[lastStepNum.subStepNum]; |
| 788 | |
| 789 | // Add finishedQueue as the last queue after the last actual processing step |
| 790 | lastStage->nextQueue = &finishedQueue; |
| 791 | lastStage->nextDone = &processingDone; |
| 792 | |
| 793 | auto firstStepNum = subStepList.front(); |
| 794 | firstStage = steps[firstStepNum.threadNum].stages[firstStepNum.subStepNum].get(); |
| 795 | } |
| 796 | |
| 797 | TxQueue &inputQueue() { |
| 798 | assert(firstStage != nullptr); |