PathFinder
PathFinder copied to clipboard
Singleton-based approach breaks multi-threading.
As far as I can tell there is no reason why Path Algorithm
specialisations need to be singletons; it provides no particular benefit (to AStar
, anyway) and it prevents the library from working properly in multithreaded workloads. The fix is trivial, simply allowing the Pathfinder
class to create a new instance of the algorithm class and using that (and making sure to call clear()
before returning the found path).
You're right there isn't a compelling reason for using singletons. I wouldn't write it this way nowadays :) I'm not actively maintaining this code anymore but feel free to propose a PR and I'll eventually merge it!
I have to point out that Singletons aren't the only thing breaking multi-threading.
I looked into this but it would require deeper changes.
Right now each time the algorithm is run, the nodes themselves are modified; which breaks multithreading.
In other words the following routines (and more importantly the variables they modify) would have to be moved outside the node and kept somewhere else or in a way that is multithread-friendly:
-
AStarNode::setOpen
-
AStarNode::setClose
-
AStarNode::setF
-
AStarNode::setG
-
AStarNode::setH
-
Node::setParent
The least intrusive way I can think of is to have this data live in a std::vector<> where the size of the vector is the max number of threads:
class AStarNode : public Node
{
struct PerThread
{
float m_f, m_g, m_h;
bool open, closed;
};
std::vector<PerThread> t;
}
And modify all functions to use a thread idx (or use a global TLS).
Anyway, that is the least intrusive method I can think of and even then it requires a big rewrite.
Alternatively, you can just clone the nodes along with their child/parent relationships for every thread and thus the only thing you'd need to solve would be the singleton.