ai_worker.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "ai_worker.h"
  2. #include "systems/ai_system/ai_behavior_registry.h"
  3. #include "systems/ai_system/ai_executor.h"
  4. #include "systems/ai_system/ai_reasoner.h"
  5. #include "systems/ai_system/ai_types.h"
  6. #include <atomic>
  7. #include <mutex>
  8. #include <queue>
  9. #include <utility>
  10. namespace Game::Systems::AI {
  11. AIWorker::AIWorker(AIReasoner &reasoner, AIExecutor &executor,
  12. AIBehaviorRegistry &registry)
  13. : m_reasoner(reasoner), m_executor(executor), m_registry(registry) {
  14. m_thread = std::thread(&AIWorker::worker_loop, this);
  15. }
  16. AIWorker::~AIWorker() {
  17. stop();
  18. { std::lock_guard<std::mutex> const lock(m_job_mutex); }
  19. m_job_condition.notify_all();
  20. if (m_thread.joinable()) {
  21. m_thread.join();
  22. }
  23. }
  24. auto AIWorker::try_submit(AIJob &&job) -> bool {
  25. if (m_worker_busy.load(std::memory_order_acquire)) {
  26. return false;
  27. }
  28. {
  29. std::lock_guard<std::mutex> const lock(m_job_mutex);
  30. m_pending_job = std::move(job);
  31. m_has_pending_job = true;
  32. }
  33. m_worker_busy.store(true, std::memory_order_release);
  34. m_job_condition.notify_one();
  35. return true;
  36. }
  37. void AIWorker::drain_results(std::queue<AIResult> &out) {
  38. std::lock_guard<std::mutex> const lock(m_result_mutex);
  39. while (!m_results.empty()) {
  40. out.push(std::move(m_results.front()));
  41. m_results.pop();
  42. }
  43. }
  44. void AIWorker::stop() { m_should_stop.store(true, std::memory_order_release); }
  45. void AIWorker::worker_loop() {
  46. while (true) {
  47. AIJob job;
  48. {
  49. std::unique_lock<std::mutex> lock(m_job_mutex);
  50. m_job_condition.wait(lock, [this]() {
  51. return m_should_stop.load(std::memory_order_acquire) ||
  52. m_has_pending_job;
  53. });
  54. if (m_should_stop.load(std::memory_order_acquire) && !m_has_pending_job) {
  55. break;
  56. }
  57. job = std::move(m_pending_job);
  58. m_has_pending_job = false;
  59. }
  60. try {
  61. AIResult result;
  62. result.context = job.context;
  63. Game::Systems::AI::AIReasoner::update_context(job.snapshot,
  64. result.context);
  65. Game::Systems::AI::AIReasoner::update_state_machine(
  66. job.snapshot, result.context, job.delta_time);
  67. Game::Systems::AI::AIReasoner::validate_state(result.context);
  68. Game::Systems::AI::AIExecutor::run(job.snapshot, result.context,
  69. job.delta_time, m_registry,
  70. result.commands);
  71. {
  72. std::lock_guard<std::mutex> const lock(m_result_mutex);
  73. m_results.push(std::move(result));
  74. }
  75. } catch (...) {
  76. }
  77. m_worker_busy.store(false, std::memory_order_release);
  78. }
  79. m_worker_busy.store(false, std::memory_order_release);
  80. }
  81. } // namespace Game::Systems::AI