ai_worker.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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_jobMutex); }
  19. m_jobCondition.notify_all();
  20. if (m_thread.joinable()) {
  21. m_thread.join();
  22. }
  23. }
  24. auto AIWorker::try_submit(AIJob &&job) -> bool {
  25. if (m_workerBusy.load(std::memory_order_acquire)) {
  26. return false;
  27. }
  28. {
  29. std::lock_guard<std::mutex> const lock(m_jobMutex);
  30. m_pendingJob = std::move(job);
  31. m_hasPendingJob = true;
  32. }
  33. m_workerBusy.store(true, std::memory_order_release);
  34. m_jobCondition.notify_one();
  35. return true;
  36. }
  37. void AIWorker::drain_results(std::queue<AIResult> &out) {
  38. std::lock_guard<std::mutex> const lock(m_resultMutex);
  39. while (!m_results.empty()) {
  40. out.push(std::move(m_results.front()));
  41. m_results.pop();
  42. }
  43. }
  44. void AIWorker::stop() { m_shouldStop.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_jobMutex);
  50. m_jobCondition.wait(lock, [this]() {
  51. return m_shouldStop.load(std::memory_order_acquire) || m_hasPendingJob;
  52. });
  53. if (m_shouldStop.load(std::memory_order_acquire) && !m_hasPendingJob) {
  54. break;
  55. }
  56. job = std::move(m_pendingJob);
  57. m_hasPendingJob = false;
  58. }
  59. try {
  60. AIResult result;
  61. result.context = job.context;
  62. Game::Systems::AI::AIReasoner::update_context(job.snapshot,
  63. result.context);
  64. Game::Systems::AI::AIReasoner::update_state_machine(
  65. job.snapshot, result.context, job.delta_time);
  66. Game::Systems::AI::AIReasoner::validate_state(result.context);
  67. Game::Systems::AI::AIExecutor::run(job.snapshot, result.context,
  68. job.delta_time, m_registry,
  69. result.commands);
  70. {
  71. std::lock_guard<std::mutex> const lock(m_resultMutex);
  72. m_results.push(std::move(result));
  73. }
  74. } catch (...) {
  75. }
  76. m_workerBusy.store(false, std::memory_order_release);
  77. }
  78. m_workerBusy.store(false, std::memory_order_release);
  79. }
  80. } // namespace Game::Systems::AI