Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
PathfindingManager.cpp
Go to the documentation of this file.
1/**
2 * @file PathfindingManager.cpp
3 * @brief Async pathfinding request manager implementation.
4 * @author Olympe Engine
5 * @date 2026-02-24
6 *
7 * @details
8 * Workers are spawned as detached std::threads. Each worker holds a raw
9 * pointer to the PathfindingManager instance; because the manager is a
10 * Meyer's singleton (static local) that lives until program exit, the
11 * pointer remains valid for the entire application lifetime.
12 *
13 * C++14 compliant - no C++17/20 features.
14 */
15
16#include "PathfindingManager.h"
17
18#include <sstream>
19#include <thread>
20
21#include "../../system/system_utils.h"
22
23namespace Olympe {
24
25// ---------------------------------------------------------------------------
26// Singleton
27// ---------------------------------------------------------------------------
28
30{
31 static PathfindingManager s_instance;
32 return s_instance;
33}
34
39
40// ---------------------------------------------------------------------------
41// Request
42// ---------------------------------------------------------------------------
43
45PathfindingManager::Request(const ::Vector& start,
46 const ::Vector& target,
47 float delaySeconds)
48{
49 RequestID id = m_nextID.fetch_add(1u);
50
51 {
52 std::lock_guard<std::mutex> lock(m_mutex);
54 entry.start = start;
55 entry.target = target;
56 entry.completed = false;
57 entry.cancelled = false;
58 m_requests[id] = entry;
59 }
60
61 SYSTEM_LOG << "[PathfindingManager] Submitted request " << id
62 << " from (" << start.x << "," << start.y << ")"
63 << " to (" << target.x << "," << target.y << ")"
64 << " delay=" << delaySeconds << "s\n";
65
66 // Spawn a detached worker thread. The lambda captures the manager pointer
67 // (safe: singleton lives until program exit) plus the request parameters
68 // by value to avoid data races.
69 PathfindingManager* mgr = this;
70 std::thread worker([mgr, id, start, target, delaySeconds]()
71 {
72 // Simulate pathfinding computation delay.
73 if (delaySeconds > 0.0f)
74 {
75 using namespace std::chrono;
76 auto ms = static_cast<long long>(delaySeconds * 1000.0f);
77 std::this_thread::sleep_for(milliseconds(ms));
78 }
79
80 std::lock_guard<std::mutex> lock(mgr->m_mutex);
81
82 auto it = mgr->m_requests.find(id);
83 if (it == mgr->m_requests.end() || it->second.cancelled)
84 {
85 SYSTEM_LOG << "[PathfindingManager] Request " << id
86 << " was cancelled - discarding result\n";
87 return;
88 }
89
90 // Build straight-line path string: "(sx,sy,sz)->(tx,ty,tz)"
91 std::ostringstream oss;
92 oss << "(" << start.x << "," << start.y << "," << start.z << ")"
93 << "->"
94 << "(" << target.x << "," << target.y << "," << target.z << ")";
95
96 it->second.result = oss.str();
97 it->second.completed = true;
98
99 SYSTEM_LOG << "[PathfindingManager] Request " << id
100 << " completed: " << it->second.result << "\n";
101 });
102 worker.detach();
103
104 return id;
105}
106
107// ---------------------------------------------------------------------------
108// IsComplete
109// ---------------------------------------------------------------------------
110
112{
113 std::lock_guard<std::mutex> lock(m_mutex);
114 auto it = m_requests.find(id);
115 if (it == m_requests.end())
116 {
117 return false;
118 }
119 return it->second.completed;
120}
121
122// ---------------------------------------------------------------------------
123// GetPathString
124// ---------------------------------------------------------------------------
125
127{
128 std::lock_guard<std::mutex> lock(m_mutex);
129 auto it = m_requests.find(id);
130 if (it == m_requests.end() || !it->second.completed)
131 {
132 return std::string();
133 }
134 return it->second.result;
135}
136
137// ---------------------------------------------------------------------------
138// Cancel
139// ---------------------------------------------------------------------------
140
142{
143 std::lock_guard<std::mutex> lock(m_mutex);
144 auto it = m_requests.find(id);
145 if (it == m_requests.end())
146 {
147 return;
148 }
149 it->second.cancelled = true;
150 m_requests.erase(it);
151
152 SYSTEM_LOG << "[PathfindingManager] Request " << id << " cancelled\n";
153}
154
155} // namespace Olympe
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Async pathfinding request manager for the Atomic Task System.
Singleton async pathfinding request manager.
static PathfindingManager & Get()
Returns the singleton PathfindingManager instance.
uint64_t RequestID
Unique identifier for a pathfinding request.
void Cancel(RequestID id)
Cancels a pending request and removes its entry.
std::atomic< uint64_t > m_nextID
RequestID Request(const ::Vector &start, const ::Vector &target, float delaySeconds=0.0f)
Submits an async pathfinding request.
std::unordered_map< RequestID, RequestEntry > m_requests
bool IsComplete(RequestID id)
Returns true if the request identified by id has completed.
std::string GetPathString(RequestID id)
Returns the path string computed for id.
float x
Definition vector.h:25
< Provides AssetID and INVALID_ASSET_ID
#define SYSTEM_LOG