| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <omp.h> | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <chrono> | ||
| 7 | #include <cstdint> | ||
| 8 | #include <cstdlib> | ||
| 9 | #include <fstream> | ||
| 10 | #include <iostream> | ||
| 11 | #include <memory> | ||
| 12 | #include <sstream> | ||
| 13 | #include <stdexcept> | ||
| 14 | #include <string> | ||
| 15 | #include <string_view> | ||
| 16 | #include <util/include/util.hpp> | ||
| 17 | #include <utility> | ||
| 18 | |||
| 19 | namespace ppc::task { | ||
| 20 | |||
| 21 | /// @brief Represents the type of task (parallelization technology). | ||
| 22 | /// @details Used to select the implementation type in tests and execution logic. | ||
| 23 | enum class TypeOfTask : uint8_t { | ||
| 24 | /// Use all available implementations | ||
| 25 | kALL, | ||
| 26 | /// MPI (Message Passing Interface) | ||
| 27 | kMPI, | ||
| 28 | /// OpenMP (Open Multi-Processing) | ||
| 29 | kOMP, | ||
| 30 | /// Sequential implementation | ||
| 31 | kSEQ, | ||
| 32 | /// Standard Thread Library (STL threads) | ||
| 33 | kSTL, | ||
| 34 | /// Intel Threading Building Blocks (TBB) | ||
| 35 | kTBB, | ||
| 36 | /// Unknown task type | ||
| 37 | kUnknown, | ||
| 38 | }; | ||
| 39 | |||
| 40 | using TaskMapping = std::pair<TypeOfTask, std::string_view>; | ||
| 41 | using TaskMappingArray = std::array<TaskMapping, 6>; | ||
| 42 | |||
| 43 | inline constexpr TaskMappingArray kTaskTypeMappings = {{{TypeOfTask::kALL, "all"}, | ||
| 44 | {TypeOfTask::kMPI, "mpi"}, | ||
| 45 | {TypeOfTask::kOMP, "omp"}, | ||
| 46 | {TypeOfTask::kSEQ, "seq"}, | ||
| 47 | {TypeOfTask::kSTL, "stl"}, | ||
| 48 | {TypeOfTask::kTBB, "tbb"}}}; | ||
| 49 | |||
| 50 | constexpr std::string_view TypeOfTaskToString(TypeOfTask type) { | ||
| 51 |
4/6✓ Branch 0 taken 1466 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1576 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3082 | for (const auto &[key, value] : kTaskTypeMappings) { |
| 52 |
4/6✓ Branch 0 taken 398 times.
✓ Branch 1 taken 1068 times.
✓ Branch 2 taken 428 times.
✓ Branch 3 taken 1148 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3042 | if (key == type) { |
| 53 | 826 | return value; | |
| 54 | } | ||
| 55 | } | ||
| 56 | return "unknown"; | ||
| 57 | } | ||
| 58 | |||
| 59 | 76 | constexpr TypeOfTask TypeOfTaskFromString(std::string_view type) { | |
| 60 |
1/2✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
|
308 | for (const auto &[key, value] : kTaskTypeMappings) { |
| 61 | 232 | if (value == type) { | |
| 62 | 76 | return key; | |
| 63 | } | ||
| 64 | } | ||
| 65 | return TypeOfTask::kUnknown; | ||
| 66 | } | ||
| 67 | |||
| 68 | /// @brief Indicates whether a task is enabled or disabled. | ||
| 69 | enum class StatusOfTask : uint8_t { | ||
| 70 | /// Task is enabled and should be executed | ||
| 71 | kEnabled, | ||
| 72 | /// Task is disabled and will be skipped | ||
| 73 | kDisabled, | ||
| 74 | }; | ||
| 75 | |||
| 76 | constexpr std::string_view StatusOfTaskToString(StatusOfTask status_of_task) { | ||
| 77 |
1/2✓ Branch 0 taken 318 times.
✗ Branch 1 not taken.
|
398 | return status_of_task == StatusOfTask::kDisabled ? "disabled" : "enabled"; |
| 78 | } | ||
| 79 | |||
| 80 |
2/2✓ Branch 0 taken 388 times.
✓ Branch 1 taken 10 times.
|
398 | inline StatusOfTask StatusOfTaskFromString(std::string_view status_of_task) { |
| 81 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (status_of_task == "enabled") { |
| 82 | 388 | return StatusOfTask::kEnabled; | |
| 83 | } | ||
| 84 | 10 | if (status_of_task == "disabled") { | |
| 85 | 10 | return StatusOfTask::kDisabled; | |
| 86 | } | ||
| 87 | ✗ | throw std::runtime_error("Unknown task status: " + std::string(status_of_task)); | |
| 88 | } | ||
| 89 | |||
| 90 | /// @brief Returns a string representation of the task status. | ||
| 91 | /// @param status_of_task Task status (enabled or disabled). | ||
| 92 | /// @return "enabled" if the task is enabled, otherwise "disabled". | ||
| 93 | inline std::string GetStringTaskStatus(StatusOfTask status_of_task) { | ||
| 94 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | return std::string(StatusOfTaskToString(status_of_task)); |
| 95 | } | ||
| 96 | |||
| 97 | enum class TaskCategory : uint8_t { | ||
| 98 | kUnknown, | ||
| 99 | kThreads, | ||
| 100 | kProcesses, | ||
| 101 | }; | ||
| 102 | |||
| 103 | constexpr std::string_view TaskCategoryToString(TaskCategory category) { | ||
| 104 | ✗ | switch (category) { | |
| 105 | case TaskCategory::kThreads: | ||
| 106 | return "threads"; | ||
| 107 | ✗ | case TaskCategory::kProcesses: | |
| 108 | return "processes"; | ||
| 109 | case TaskCategory::kUnknown: | ||
| 110 | return ""; | ||
| 111 | } | ||
| 112 | return ""; | ||
| 113 | } | ||
| 114 | |||
| 115 | 318 | constexpr TaskCategory TaskCategoryFromSettingsPath(std::string_view settings_task_path) { | |
| 116 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 150 times.
|
318 | if (settings_task_path.starts_with("threads")) { |
| 117 | return TaskCategory::kThreads; | ||
| 118 | } | ||
| 119 |
1/2✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
|
168 | if (settings_task_path.starts_with("processes")) { |
| 120 | 168 | return TaskCategory::kProcesses; | |
| 121 | } | ||
| 122 | return TaskCategory::kUnknown; | ||
| 123 | } | ||
| 124 | |||
| 125 |
15/30✗ Branch 0 not taken.
✓ Branch 1 taken 122 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 112 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 112 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 112 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 28 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 28 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 28 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 28 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 28 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 28 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 28 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 28 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 28 times.
|
1252 | struct TaskDescriptor { |
| 126 | TypeOfTask type = TypeOfTask::kUnknown; | ||
| 127 | StatusOfTask status = StatusOfTask::kEnabled; | ||
| 128 | TaskCategory category = TaskCategory::kUnknown; | ||
| 129 | std::string display_name; | ||
| 130 | }; | ||
| 131 | |||
| 132 | /// @brief Returns a string representation of the task type based on the JSON settings file. | ||
| 133 | /// @param type_of_task Type of the task. | ||
| 134 | /// @param settings_file_path Path to the JSON file containing task type strings. | ||
| 135 | /// @param settings_task_path Optional dot-separated nested path inside the `tasks` object. | ||
| 136 | /// @return Formatted string combining the task type and its corresponding value from the file. | ||
| 137 | /// @throws std::runtime_error If the file cannot be opened or the requested settings key is missing. | ||
| 138 | 478 | inline StatusOfTask GetTaskStatus(TypeOfTask type_of_task, const std::string &settings_file_path, | |
| 139 | std::string_view settings_task_path = {}) { | ||
| 140 | 478 | std::ifstream file(settings_file_path); | |
| 141 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 458 times.
|
478 | if (!file.is_open()) { |
| 142 |
2/4✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
40 | throw std::runtime_error("Failed to open " + settings_file_path); |
| 143 | } | ||
| 144 | |||
| 145 | auto list_settings = ppc::util::InitJSONPtr(); | ||
| 146 |
2/2✓ Branch 1 taken 448 times.
✓ Branch 2 taken 10 times.
|
458 | file >> *list_settings; |
| 147 | |||
| 148 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 428 times.
|
448 | const std::string_view type_str = TypeOfTaskToString(type_of_task); |
| 149 | 448 | if (type_str == "unknown") { | |
| 150 | 20 | return StatusOfTask::kEnabled; | |
| 151 | } | ||
| 152 | |||
| 153 |
1/2✓ Branch 0 taken 1392 times.
✗ Branch 1 not taken.
|
1392 | auto get_required_node = [&settings_file_path](const nlohmann::json &node, const std::string &key, |
| 154 | const std::string &settings_key_path) -> const nlohmann::json & { | ||
| 155 |
1/2✓ Branch 0 taken 1392 times.
✗ Branch 1 not taken.
|
1392 | if (!node.is_object() || !node.contains(key)) { |
| 156 |
2/4✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
60 | throw std::runtime_error("Missing settings key '" + settings_key_path + "' in " + settings_file_path); |
| 157 | } | ||
| 158 | 1372 | return *node.find(key); | |
| 159 | 428 | }; | |
| 160 | |||
| 161 |
1/2✓ Branch 1 taken 428 times.
✗ Branch 2 not taken.
|
468 | std::string settings_key_path = "tasks"; |
| 162 |
2/4✓ Branch 1 taken 428 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 428 times.
✗ Branch 5 not taken.
|
428 | const auto *settings_node = &get_required_node(*list_settings, "tasks", settings_key_path); |
| 163 |
2/2✓ Branch 0 taken 546 times.
✓ Branch 1 taken 80 times.
|
626 | for (size_t start = 0; start < settings_task_path.size();) { |
| 164 | 546 | const size_t separator = settings_task_path.find('.', start); | |
| 165 |
2/2✓ Branch 0 taken 348 times.
✓ Branch 1 taken 198 times.
|
546 | const size_t key_size = separator == std::string_view::npos ? settings_task_path.size() - start : separator - start; |
| 166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 546 times.
|
546 | if (key_size == 0) { |
| 167 | ✗ | throw std::runtime_error("Empty settings key in '" + std::string(settings_task_path) + "' from " + | |
| 168 | ✗ | settings_file_path); | |
| 169 | } | ||
| 170 |
1/2✓ Branch 1 taken 546 times.
✗ Branch 2 not taken.
|
546 | const std::string key(settings_task_path.substr(start, key_size)); |
| 171 |
2/4✓ Branch 1 taken 546 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
556 | settings_key_path += "." + key; |
| 172 |
2/2✓ Branch 1 taken 536 times.
✓ Branch 2 taken 10 times.
|
546 | settings_node = &get_required_node(*settings_node, key, settings_key_path); |
| 173 |
2/2✓ Branch 0 taken 198 times.
✓ Branch 1 taken 338 times.
|
536 | if (separator == std::string_view::npos) { |
| 174 | break; | ||
| 175 | } | ||
| 176 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | start = separator + 1; |
| 177 | } | ||
| 178 | |||
| 179 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
|
30 | const std::string type_key(type_str); |
| 180 |
1/2✓ Branch 1 taken 418 times.
✗ Branch 2 not taken.
|
418 | settings_key_path += "." + type_key; |
| 181 |
2/2✓ Branch 1 taken 408 times.
✓ Branch 2 taken 10 times.
|
418 | const auto &type_node = get_required_node(*settings_node, type_key, settings_key_path); |
| 182 |
3/6✓ Branch 1 taken 398 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 398 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
816 | return StatusOfTaskFromString(type_node.get<std::string>()); |
| 183 | 478 | } | |
| 184 | |||
| 185 | 160 | inline std::string GetStringTaskType(TypeOfTask type_of_task, const std::string &settings_file_path, | |
| 186 | std::string_view settings_task_path = {}) { | ||
| 187 | 160 | const StatusOfTask status = GetTaskStatus(type_of_task, settings_file_path, settings_task_path); | |
| 188 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 80 times.
|
100 | const std::string_view type_str = TypeOfTaskToString(type_of_task); |
| 189 |
2/2✓ Branch 1 taken 70 times.
✓ Branch 2 taken 10 times.
|
100 | if (type_str == "unknown") { |
| 190 | 20 | return std::string(type_str); | |
| 191 | } | ||
| 192 |
2/6✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
240 | return std::string(type_str) + "_" + std::string(StatusOfTaskToString(status)); |
| 193 | } | ||
| 194 | |||
| 195 | enum class StateOfTesting : uint8_t { | ||
| 196 | kFunc, | ||
| 197 | kPerf, | ||
| 198 | }; | ||
| 199 | |||
| 200 | template <typename InType, typename OutType> | ||
| 201 | /// @brief Base abstract class representing a generic task with a defined pipeline. | ||
| 202 | /// @tparam InType Input data type. | ||
| 203 | /// @tparam OutType Output data type. | ||
| 204 | class Task { | ||
| 205 | public: | ||
| 206 | using InputType = InType; | ||
| 207 | using OutputType = OutType; | ||
| 208 | |||
| 209 | 40 | Task() = default; | |
| 210 |
10/20✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 10 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 10 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 10 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 10 times.
✗ Branch 27 not taken.
✓ Branch 29 taken 10 times.
✗ Branch 30 not taken.
|
273 | explicit Task(InType input, TypeOfTask type_of_task) : input_(std::move(input)), type_of_task_(type_of_task) {} |
| 211 | Task(const Task &) = delete; | ||
| 212 | Task(Task &&) = delete; | ||
| 213 | Task &operator=(const Task &) = delete; | ||
| 214 | Task &operator=(Task &&) = delete; | ||
| 215 | |||
| 216 | /// @brief Validates input data and task attributes before execution. | ||
| 217 | /// @return True if validation is successful. | ||
| 218 | 418 | virtual bool Validation() final { | |
| 219 |
2/2✓ Branch 0 taken 283 times.
✓ Branch 1 taken 10 times.
|
418 | if (stage_ == PipelineStage::kNone || stage_ == PipelineStage::kDone) { |
| 220 | 398 | stage_ = PipelineStage::kValidation; | |
| 221 | } else { | ||
| 222 | 20 | stage_ = PipelineStage::kException; | |
| 223 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | throw std::runtime_error("Validation should be called before preprocessing"); |
| 224 | } | ||
| 225 | 398 | return ValidationImpl(); | |
| 226 | } | ||
| 227 | |||
| 228 | /// @brief Performs preprocessing on the input data. | ||
| 229 | /// @return True if preprocessing is successful. | ||
| 230 | 398 | virtual bool PreProcessing() final { | |
| 231 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 20 times.
|
398 | if (stage_ == PipelineStage::kValidation) { |
| 232 | 358 | stage_ = PipelineStage::kPreProcessing; | |
| 233 | } else { | ||
| 234 | 40 | stage_ = PipelineStage::kException; | |
| 235 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
40 | throw std::runtime_error("Preprocessing should be called after validation"); |
| 236 | } | ||
| 237 |
1/2✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
|
358 | if (state_of_testing_ == StateOfTesting::kFunc) { |
| 238 | 358 | InternalTimeTest(); | |
| 239 | } | ||
| 240 | 358 | return PreProcessingImpl(); | |
| 241 | } | ||
| 242 | |||
| 243 | /// @brief Executes the main logic of the task. | ||
| 244 | /// @return True if execution is successful. | ||
| 245 | 348 | virtual bool Run() final { | |
| 246 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 10 times.
|
348 | if (stage_ == PipelineStage::kPreProcessing || stage_ == PipelineStage::kRun) { |
| 247 | 328 | stage_ = PipelineStage::kRun; | |
| 248 | } else { | ||
| 249 | 20 | stage_ = PipelineStage::kException; | |
| 250 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | throw std::runtime_error("Run should be called after preprocessing"); |
| 251 | } | ||
| 252 | 328 | return RunImpl(); | |
| 253 | } | ||
| 254 | |||
| 255 | /// @brief Performs postprocessing on the output data. | ||
| 256 | /// @return True if postprocessing is successful. | ||
| 257 | 398 | virtual bool PostProcessing() final { | |
| 258 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 35 times.
|
398 | if (stage_ == PipelineStage::kRun) { |
| 259 | 328 | stage_ = PipelineStage::kDone; | |
| 260 | } else { | ||
| 261 | 70 | stage_ = PipelineStage::kException; | |
| 262 |
1/2✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
|
70 | throw std::runtime_error("Postprocessing should be called after run"); |
| 263 | } | ||
| 264 |
1/2✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
|
328 | if (state_of_testing_ == StateOfTesting::kFunc) { |
| 265 | 328 | InternalTimeTest(); | |
| 266 | } | ||
| 267 | 288 | return PostProcessingImpl(); | |
| 268 | } | ||
| 269 | |||
| 270 | /// @brief Sets the current testing mode. | ||
| 271 | void SetStateOfTesting(StateOfTesting state_of_testing) { | ||
| 272 | ✗ | state_of_testing_ = state_of_testing; | |
| 273 | } | ||
| 274 | |||
| 275 | /// @brief Returns the current testing mode. | ||
| 276 | [[nodiscard]] StateOfTesting GetStateOfTesting() const { | ||
| 277 | return state_of_testing_; | ||
| 278 | } | ||
| 279 | |||
| 280 | /// @brief Returns the dynamic task type. | ||
| 281 | /// @return Current dynamic task type. | ||
| 282 | [[nodiscard]] TypeOfTask GetDynamicTypeOfTask() const { | ||
| 283 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | return type_of_task_; |
| 284 | } | ||
| 285 | |||
| 286 | /// @brief Returns the static task type. | ||
| 287 | /// @return Static task type (default: kUnknown). | ||
| 288 | static constexpr TypeOfTask GetStaticTypeOfTask() { | ||
| 289 | return TypeOfTask::kUnknown; | ||
| 290 | } | ||
| 291 | |||
| 292 | /// @brief Returns a reference to the input data. | ||
| 293 | /// @return Reference to the task's input data. | ||
| 294 | [[nodiscard]] const InType &GetInput() const { | ||
| 295 | return input_; | ||
| 296 | } | ||
| 297 | |||
| 298 | /// @brief Returns a reference to the output data. | ||
| 299 | /// @return Reference to the task's output data. | ||
| 300 | [[nodiscard]] const OutType &GetOutput() const { | ||
| 301 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
168 | return output_; |
| 302 | } | ||
| 303 | |||
| 304 | /// @brief Destructor. Verifies that the pipeline was executed in the correct order. | ||
| 305 | /// @note Terminates the program if the pipeline order is incorrect or incomplete. | ||
| 306 | 230 | virtual ~Task() { | |
| 307 | 240 | if (stage_ != PipelineStage::kDone && stage_ != PipelineStage::kException) { | |
| 308 | ppc::util::DestructorFailureFlag::Set(); | ||
| 309 | } | ||
| 310 | #if _OPENMP >= 201811 | ||
| 311 | omp_pause_resource_all(omp_pause_soft); | ||
| 312 | #endif | ||
| 313 |
2/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 105 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
240 | } |
| 314 | |||
| 315 | protected: | ||
| 316 | /// @brief Returns mutable access to the input for task implementations. | ||
| 317 | InType &GetMutableInput() { | ||
| 318 | return input_; | ||
| 319 | } | ||
| 320 | |||
| 321 | /// @brief Returns mutable access to the output for task implementations. | ||
| 322 | OutType &GetMutableOutput() { | ||
| 323 | return output_; | ||
| 324 | } | ||
| 325 | |||
| 326 | /// @brief Measures execution time between preprocessing and postprocessing steps. | ||
| 327 | /// @throws std::runtime_error If execution exceeds the allowed time limit. | ||
| 328 | 686 | virtual void InternalTimeTest() final { | |
| 329 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 248 times.
|
686 | if (stage_ == PipelineStage::kPreProcessing) { |
| 330 | 358 | tmp_time_point_ = std::chrono::high_resolution_clock::now(); | |
| 331 | } | ||
| 332 | |||
| 333 |
2/2✓ Branch 0 taken 248 times.
✓ Branch 1 taken 263 times.
|
686 | if (stage_ == PipelineStage::kDone) { |
| 334 | 328 | auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - | |
| 335 | tmp_time_point_) | ||
| 336 | .count(); | ||
| 337 | 328 | auto diff = static_cast<double>(duration) * 1e-9; | |
| 338 | |||
| 339 | 328 | const auto max_time = ppc::util::GetTaskMaxTime(); | |
| 340 |
2/2✓ Branch 0 taken 228 times.
✓ Branch 1 taken 20 times.
|
328 | if (diff < max_time) { |
| 341 | return; | ||
| 342 | } | ||
| 343 | |||
| 344 | 40 | std::stringstream err_msg; | |
| 345 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | err_msg << "\nTask execute time need to be: "; |
| 346 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | err_msg << "time < " << max_time << " secs.\n"; |
| 347 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | err_msg << "Original time in secs: " << diff << '\n'; |
| 348 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
120 | throw std::runtime_error(err_msg.str().c_str()); |
| 349 | 40 | } | |
| 350 | } | ||
| 351 | |||
| 352 | /// @brief User-defined validation logic. | ||
| 353 | /// @return True if validation is successful. | ||
| 354 | virtual bool ValidationImpl() = 0; | ||
| 355 | |||
| 356 | /// @brief User-defined preprocessing logic. | ||
| 357 | /// @return True if preprocessing is successful. | ||
| 358 | virtual bool PreProcessingImpl() = 0; | ||
| 359 | |||
| 360 | /// @brief User-defined task execution logic. | ||
| 361 | /// @return True if a run is successful. | ||
| 362 | virtual bool RunImpl() = 0; | ||
| 363 | |||
| 364 | /// @brief User-defined postprocessing logic. | ||
| 365 | /// @return True if postprocessing is successful. | ||
| 366 | virtual bool PostProcessingImpl() = 0; | ||
| 367 | |||
| 368 | private: | ||
| 369 | InType input_{}; | ||
| 370 | OutType output_{}; | ||
| 371 | StateOfTesting state_of_testing_ = StateOfTesting::kFunc; | ||
| 372 | TypeOfTask type_of_task_ = TypeOfTask::kUnknown; | ||
| 373 | std::chrono::high_resolution_clock::time_point tmp_time_point_; | ||
| 374 | enum class PipelineStage : uint8_t { | ||
| 375 | kNone, | ||
| 376 | kValidation, | ||
| 377 | kPreProcessing, | ||
| 378 | kRun, | ||
| 379 | kDone, | ||
| 380 | kException, | ||
| 381 | } stage_ = PipelineStage::kNone; | ||
| 382 | }; | ||
| 383 | |||
| 384 | /// @brief Smart pointer alias for Task. | ||
| 385 | /// @tparam InType Input data type. | ||
| 386 | /// @tparam OutType Output data type. | ||
| 387 | template <typename InType, typename OutType> | ||
| 388 | using TaskPtr = std::unique_ptr<Task<InType, OutType>>; | ||
| 389 | |||
| 390 | /// @brief Constructs and returns a pointer to a task with the given input. | ||
| 391 | /// @tparam TaskType Type of the task to create. | ||
| 392 | /// @tparam InType Type of the input. | ||
| 393 | /// @param in Input to pass to the task constructor. | ||
| 394 | /// @return Unique pointer to the newly created task. | ||
| 395 | template <typename TaskType, typename InType> | ||
| 396 | 336 | std::unique_ptr<TaskType> TaskGetter(InType &&in) { | |
| 397 | 336 | return std::make_unique<TaskType>(std::forward<InType>(in)); | |
| 398 | } | ||
| 399 | |||
| 400 | } // namespace ppc::task | ||
| 401 |