| 47 | namespace aimrt::runtime::core::executor { |
| 48 | |
| 49 | void GuardThreadExecutor::Initialize(YAML::Node options_node) { |
| 50 | AIMRT_CHECK_ERROR_THROW( |
| 51 | std::atomic_exchange(&state_, State::kInit) == State::kPreInit, |
| 52 | "GuardThreadExecutor can only be initialized once."); |
| 53 | |
| 54 | if (options_node && !options_node.IsNull()) |
| 55 | options_ = options_node.as<Options>(); |
| 56 | |
| 57 | name_ = options_.name; |
| 58 | |
| 59 | queue_threshold_ = options_.queue_threshold; |
| 60 | queue_warn_threshold_ = queue_threshold_ * 0.95; |
| 61 | |
| 62 | thread_ptr_ = std::make_unique<std::thread>([this]() { |
| 63 | thread_id_ = std::this_thread::get_id(); |
| 64 | |
| 65 | try { |
| 66 | util::SetNameForCurrentThread(name_); |
| 67 | util::BindCpuForCurrentThread(options_.thread_bind_cpu); |
| 68 | util::SetCpuSchedForCurrentThread(options_.thread_sched_policy); |
| 69 | } catch (const std::exception& e) { |
| 70 | AIMRT_WARN("Set thread policy for guard thread executor '{}' get exception, {}", |
| 71 | Name(), e.what()); |
| 72 | } |
| 73 | |
| 74 | while (state_.load() != State::kShutdown) { |
| 75 | // Multi-producer-single-consumer optimization |
| 76 | std::queue<aimrt::executor::Task> tmp_queue; |
| 77 | |
| 78 | { |
| 79 | std::unique_lock<std::mutex> lck(mutex_); |
| 80 | cond_.wait(lck, [this] { return !queue_.empty() || state_.load() == State::kShutdown; }); |
| 81 | queue_.swap(tmp_queue); |
| 82 | } |
| 83 | |
| 84 | while (!tmp_queue.empty()) { |
| 85 | auto& task = tmp_queue.front(); |
| 86 | |
| 87 | try { |
| 88 | task(); |
| 89 | --queue_task_num_; |
| 90 | } catch (const std::exception& e) { |
| 91 | AIMRT_FATAL("Guard thread executor run task get exception, {}", e.what()); |
| 92 | } |
| 93 | |
| 94 | tmp_queue.pop(); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Run once more after shutdown, no need for locks since no more tasks will enter the queue |
| 99 | while (!queue_.empty()) { |
| 100 | auto& task = queue_.front(); |
| 101 | |
| 102 | try { |
| 103 | task(); |
| 104 | --queue_task_num_; |
| 105 | } catch (const std::exception& e) { |
| 106 | AIMRT_FATAL("Guard thread executor run task get exception, {}", e.what()); |
nothing calls this directly
no test coverage detected