1
0
Fork 0

Use new PriorityQueue, compiles, does not work.

This commit is contained in:
Max Neunhoeffer 2015-04-24 08:43:51 -07:00 committed by Michael Hackstein
parent 3fc8243432
commit e508a1697d
3 changed files with 210 additions and 214 deletions

View File

@ -45,8 +45,6 @@ using namespace std;
using namespace triagens::basics; using namespace triagens::basics;
using namespace triagens::arango; using namespace triagens::arango;
std::mutex m;
class SimpleEdgeExpander { class SimpleEdgeExpander {
private: private:
@ -100,13 +98,8 @@ class SimpleEdgeExpander {
return edgeIdPrefix.append(key); return edgeIdPrefix.append(key);
}; };
void operator() ( Traverser::VertexId source, void operator() (Traverser::VertexId source,
Traverser::Direction dir, vector<Traverser::Step>& result) {
vector<Traverser::Neighbor>& result
) {
//std::lock_guard<std::mutex> guard(m);
// cout << "Hallole: " << id << endl;
std::vector<TRI_doc_mptr_copy_t> edges; std::vector<TRI_doc_mptr_copy_t> edges;
// Process Vertex Id! // Process Vertex Id!
size_t split; size_t split;
@ -133,19 +126,19 @@ class SimpleEdgeExpander {
// cout << edges.size() << endl; // cout << edges.size() << endl;
} }
std::unordered_map<Traverser::VertexId, Traverser::Neighbor> candidates; std::unordered_map<Traverser::VertexId, Traverser::Step> candidates;
Traverser::VertexId from; Traverser::VertexId from;
Traverser::VertexId to; Traverser::VertexId to;
std::unordered_map<Traverser::VertexId, Traverser::Neighbor>::const_iterator cand; std::unordered_map<Traverser::VertexId, Traverser::Step>::const_iterator cand;
if (usesDist) { if (usesDist) {
for (size_t j = 0; j < edges.size(); ++j) { for (size_t j = 0; j < edges.size(); ++j) {
from = extractFromId(edges[j]); from = extractFromId(edges[j]);
to = extractFromId(edges[j]); to = extractToId(edges[j]);
if (from != source) { if (from != source) {
candidates.find(from); candidates.find(from);
if (cand == candidates.end()) { if (cand == candidates.end()) {
// Add weight // Add weight
candidates.emplace(from, Traverser::Neighbor(from, edges[j]._id, 1)); candidates.emplace(from, Traverser::Step(to, from, 1, extractEdgeId(edges[j])));
} else { } else {
// Compare weight // Compare weight
} }
@ -153,7 +146,7 @@ class SimpleEdgeExpander {
candidates.find(to); candidates.find(to);
if (cand == candidates.end()) { if (cand == candidates.end()) {
// Add weight // Add weight
candidates.emplace(to, Traverser::Neighbor(to, edges[j]._id, 1)); candidates.emplace(to, Traverser::Step(from, to, 1, extractEdgeId(edges[j])));
} else { } else {
// Compare weight // Compare weight
} }
@ -166,12 +159,12 @@ class SimpleEdgeExpander {
if (from != source) { if (from != source) {
candidates.find(from); candidates.find(from);
if (cand == candidates.end()) { if (cand == candidates.end()) {
candidates.emplace(from, Traverser::Neighbor(from, edges[j]._id, 1)); candidates.emplace(from, Traverser::Step(to, from, 1, extractEdgeId(edges[j])));
} }
} else if (to != source) { } else if (to != source) {
candidates.find(to); candidates.find(to);
if (cand == candidates.end()) { if (cand == candidates.end()) {
candidates.emplace(to, Traverser::Neighbor(to, edges[j]._id, 1)); candidates.emplace(to, Traverser::Step(from, to, 1, extractEdgeId(edges[j])));
} }
} }
} }
@ -329,7 +322,7 @@ void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B"); SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B");
Traverser traverser(forwardExpander, backwardExpander); Traverser traverser(forwardExpander, backwardExpander);
unique_ptr<Traverser::Path> path(traverser.ShortestPath(startVertex, targetVertex)); unique_ptr<Traverser::Path> path(traverser.shortestPath(startVertex, targetVertex));
if (path.get() == nullptr) { if (path.get() == nullptr) {
res = trx.finish(res); res = trx.finish(res);
v8::EscapableHandleScope scope(isolate); v8::EscapableHandleScope scope(isolate);

View File

@ -23,6 +23,7 @@
/// Copyright holder is ArangoDB GmbH, Cologne, Germany /// Copyright holder is ArangoDB GmbH, Cologne, Germany
/// ///
/// @author Michael Hackstein /// @author Michael Hackstein
/// @author Max Neunhoeffer
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany /// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany /// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -58,59 +59,73 @@ class Searcher : public Thread {
private: private:
void insertNeighbor (Traverser::ThreadInfo& info, void insertNeighbor (Traverser::VertexId& neighbor,
Traverser::VertexId& neighbor,
Traverser::VertexId& predecessor, Traverser::VertexId& predecessor,
Traverser::EdgeId& edge, Traverser::EdgeId& edge,
Traverser::EdgeWeight weight) { Traverser::EdgeWeight weight) {
std::lock_guard<std::mutex> guard(info.mutex); std::lock_guard<std::mutex> guard(_myInfo._mutex);
auto it = info.lookup.find(neighbor); Traverser::Step* s = _myInfo._pq.lookup(neighbor);
// Not found, so insert it: // Not found, so insert it:
if (it == info.lookup.end()) { if (s == nullptr) {
info.lookup.emplace( _myInfo._pq.insert(neighbor,
neighbor, Traverser::Step(neighbor, predecessor,
Traverser::LookupInfo(weight, edge, predecessor) weight, edge));
);
info.queue.insert(
Traverser::QueueInfo(neighbor, weight)
);
return; return;
} }
if (it->second.done) { if (s->_done) {
return; return;
} }
if (it->second.weight > weight) { if (s->_weight > weight) {
Traverser::QueueInfo q(neighbor, it->second.weight); _myInfo._pq.lowerWeight(neighbor, weight);
info.queue.erase(q);
q.weight = weight;
info.queue.insert(q);
it->second.weight = weight;
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Lookup a neighbor in the list of our peer. /// @brief Lookup our current vertex in the data of our peer.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void lookupPeer (Traverser::ThreadInfo& info, void lookupPeer (Traverser::VertexId& vertex,
Traverser::VertexId& neighbor,
Traverser::EdgeWeight weight) { Traverser::EdgeWeight weight) {
std::lock_guard<std::mutex> guard(info.mutex); std::lock_guard<std::mutex> guard(_peerInfo._mutex);
auto it = info.lookup.find(neighbor); Traverser::Step* s = _peerInfo._pq.lookup(vertex);
if (it == info.lookup.end()) { if (s == nullptr) {
// Not found, nothing more to do
return; return;
} }
Traverser::EdgeWeight total = it->second.weight + weight; Traverser::EdgeWeight total = s->_weight + weight;
if (total < _traverser->highscore) {
_traverser->highscore = total; // Update the highscore:
std::lock_guard<std::mutex> guard2(_traverser->_resultMutex);
if (!_traverser->_highscoreSet || total < _traverser->_highscore) {
_traverser->_highscoreSet = true;
_traverser->_highscore = total;
} }
if (it->second.done && total <= _traverser->highscore) {
std::lock_guard<std::mutex> guard(_traverser->resultMutex); // Now the highscore is set!
_traverser->intermediate = neighbor;
_traverser->bingo = true; // Did we find a solution together with the other thread?
if (s->_done) {
if (total <= _traverser->_highscore) {
_traverser->_intermediate = vertex;
_traverser->_bingo = true;
}
// We found a way, but somebody else found a better way, so
// this is not the shortest path
return;
}
// Did we find a solution on our own? This is for the single thread
// case and for the case that the other thread is too slow to even
// finish its own start vertex!
if (s->_weight == 0) {
// We have found the target, we have finished all vertices with
// a smaller weight than this one (and did not succeed), so this
// must be a best solution:
_traverser->_intermediate = vertex;
_traverser->_bingo = true;
} }
} }
@ -123,30 +138,27 @@ class Searcher : public Thread {
virtual void run () { virtual void run () {
auto nextVertexIt = _myInfo.queue.begin(); Traverser::VertexId v;
std::vector<Traverser::Neighbor> neighbors; Traverser::Step s;
bool b = _myInfo._pq.popMinimal(v, s, true);
std::vector<Traverser::Step> neighbors;
// Iterate while no bingo found and // Iterate while no bingo found and
// there still is a vertex on the stack. // there still is a vertex on the stack.
while (!_traverser->bingo && nextVertexIt != _myInfo.queue.end()) { while (!_traverser->_bingo && b) {
auto nextVertex = *nextVertexIt;
_myInfo.queue.erase(nextVertexIt);
neighbors.clear(); neighbors.clear();
_expander(nextVertex.vertex, neighbors); _expander(v, neighbors);
for (auto& neighbor : neighbors) { for (auto& neighbor : neighbors) {
insertNeighbor(_myInfo, neighbor.neighbor, nextVertex.vertex, insertNeighbor(neighbor._vertex, v, neighbor._edge,
neighbor.edge, nextVertex.weight + neighbor.weight); s._weight + neighbor._weight);
} }
lookupPeer(_peerInfo, nextVertex.vertex, nextVertex.weight); lookupPeer(v, s._weight);
_myInfo.mutex.lock();
// Can move nextVertexLookup up?
auto nextVertexLookup = _myInfo.lookup.find(nextVertex.vertex);
TRI_ASSERT(nextVertexLookup != _myInfo.lookup.end()); std::lock_guard<std::mutex> guard(_myInfo._mutex);
Traverser::Step* s2 = _myInfo._pq.lookup(v);
nextVertexLookup->second.done = true; s2->_done = true;
_myInfo.mutex.unlock(); b = _myInfo._pq.popMinimal(v, s, true);
nextVertexIt = _myInfo.queue.begin();
} }
} }
}; };
@ -155,62 +167,60 @@ class Searcher : public Thread {
/// @brief return the shortest path between the start and target vertex. /// @brief return the shortest path between the start and target vertex.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Traverser::Path* Traverser::ShortestPath (VertexId const& start, Traverser::Path* Traverser::shortestPath (VertexId const& start,
VertexId const& target) { VertexId const& target) {
// For the result:
std::deque<VertexId> r_vertices; std::deque<VertexId> r_vertices;
std::deque<VertexId> r_edges; std::deque<VertexId> r_edges;
highscore = 1e50; _highscoreSet = false;
bingo = false; _highscore = 0;
_bingo = false;
// Forward with initialization: // Forward with initialization:
_forwardLookup.clear(); string empty;
_forwardLookup.emplace(start, LookupInfo(0, "", "")); ThreadInfo forward;
_forwardQueue.clear(); forward._pq.insert(start, Step(start, empty, 0, empty));
_forwardQueue.insert(QueueInfo(start, 0));
ThreadInfo forwardInfo(_forwardLookup, _forwardQueue, _forwardMutex);
_backwardLookup.clear(); // backward with initialization:
_backwardLookup.emplace(target, LookupInfo(0, "", "")); ThreadInfo backward;
_backwardQueue.clear(); backward._pq.insert(target, Step(target, empty, 0, empty));
_backwardQueue.insert(QueueInfo(target, 0));
ThreadInfo backwardInfo(_backwardLookup, _backwardQueue, _backwardMutex);
Searcher forwardSearcher(this, forwardInfo, backwardInfo, start, // Now the searcher threads:
_forwardExpander, "X"); Searcher forwardSearcher(this, forward, backward, start,
Searcher backwardSearcher(this, backwardInfo, forwardInfo, target, _forwardExpander, "Forward");
_backwardExpander, "Y"); Searcher backwardSearcher(this, backward, forward, target,
_backwardExpander, "Backward");
forwardSearcher.start(); forwardSearcher.start();
backwardSearcher.start(); backwardSearcher.start();
forwardSearcher.join(); forwardSearcher.join();
backwardSearcher.join(); backwardSearcher.join();
if (!bingo || intermediate == "") { if (!_bingo || _intermediate == "") {
return nullptr; return nullptr;
} }
auto pathLookup = _forwardLookup.find(intermediate); Step* s = forward._pq.lookup(_intermediate);
r_vertices.push_back(_intermediate);
// FORWARD Go path back from intermediate -> start. // FORWARD Go path back from intermediate -> start.
// Insert all vertices and edges at front of vector // Insert all vertices and edges at front of vector
// Do NOT! insert the intermediate vertex // Do NOT! insert the intermediate vertex
TRI_ASSERT(pathLookup != _forwardLookup.end()); while (s->_predecessor != "") {
r_vertices.push_back(intermediate); r_edges.push_front(s->_edge);
while (pathLookup->second.predecessor != "") { r_vertices.push_front(s->_predecessor);
r_edges.push_front(pathLookup->second.edge); s = forward._pq.lookup(s->_predecessor);
r_vertices.push_front(pathLookup->second.predecessor);
pathLookup = _forwardLookup.find(pathLookup->second.predecessor);
} }
// BACKWARD Go path back from intermediate -> target. // BACKWARD Go path back from intermediate -> target.
// Insert all vertices and edges at back of vector // Insert all vertices and edges at back of vector
// Also insert the intermediate vertex // Also insert the intermediate vertex
pathLookup = _backwardLookup.find(intermediate); s = backward._pq.lookup(_intermediate);
TRI_ASSERT(pathLookup != _backwardLookup.end()); while (s->_predecessor != "") {
while (pathLookup->second.predecessor != "") { r_edges.push_back(s->_edge);
r_edges.push_back(pathLookup->second.edge); r_vertices.push_back(s->_predecessor);
r_vertices.push_back(pathLookup->second.predecessor); s = backward._pq.lookup(s->_predecessor);
pathLookup = _backwardLookup.find(pathLookup->second.predecessor);
} }
Path* res = new Path(r_vertices, r_edges, highscore); return new Path(r_vertices, r_edges, _highscore);
return res;
}; };

View File

@ -34,8 +34,6 @@
#include <mutex> #include <mutex>
class Searcher;
namespace triagens { namespace triagens {
namespace basics { namespace basics {
@ -158,21 +156,22 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief lookup /// @brief lookup, note that the resulting pointer is only valid until the
/// the next modification of the data structure happens (insert or lowerWeight
/// or popMinimal). The weight in the Value type must not be modified other
/// than via lowerWeight, otherwise the queue order could be violated.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Value const* lookup (Key const& k) { Value* lookup (Key const& k) {
auto it = _lookup.find(k); auto it = _lookup.find(k);
if (it == _lookup.end()) { if (it == _lookup.end()) {
return nullptr; return nullptr;
} }
if (it->second >= 0) { // still in the queue if (it->second >= 0) { // still in the queue
return const_cast<Value const*> return &(_heap[static_cast<size_t>(it->second) - _popped]);
(&(_heap[static_cast<size_t>(it->second) - _popped]));
} }
else { // already in the history else { // already in the history
return const_cast<Value const*> return &(_history[static_cast<size_t>(-it->second) - 1]);
(&(_history[static_cast<size_t>(-it->second) - 1]));
} }
} }
@ -201,19 +200,24 @@ namespace triagens {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief getMinimal /// @brief getMinimal, note that the resulting pointer is only valid until the
/// the next modification of the data structure happens (insert or lowerWeight
/// or popMinimal). The weight in the Value type must not be modified other
/// than via lowerWeight, otherwise the queue order could be violated.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Value const* getMinimal() { Value* getMinimal() {
if (_heap.empty()) { if (_heap.empty()) {
return nullptr; return nullptr;
} }
return const_cast<Value const*>(&(_heap[0])); return &(_heap[0]);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief popMinimal, returns true if something was returned and false /// @brief popMinimal, returns true if something was returned and false
/// if the structure is empty. Key and Value are stored in k and v. /// if the structure is empty. Key and Value are stored in k and v.
/// If keepForLookup is true then the Value is kept for lookup in the
/// hash table but removed from the priority queue.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool popMinimal (Key& k, Value& v, bool keepForLookup = false) { bool popMinimal (Key& k, Value& v, bool keepForLookup = false) {
@ -358,15 +362,6 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void removeFromHeap (bool keepForLookup) { void removeFromHeap (bool keepForLookup) {
if (_heap.size() == 1) {
_heap.clear();
_popped = 0;
_lookup.clear();
_isHeap = false;
_maxWeight = 0;
return;
}
auto it = _lookup.find(_heap[0].getKey()); auto it = _lookup.find(_heap[0].getKey());
TRI_ASSERT(it != _lookup.end()); TRI_ASSERT(it != _lookup.end());
if (keepForLookup) { if (keepForLookup) {
@ -377,6 +372,14 @@ namespace triagens {
else { else {
_lookup.erase(it); _lookup.erase(it);
} }
if (_heap.size() == 1) {
_heap.clear();
_popped = 0;
_isHeap = false;
_maxWeight = 0;
return;
}
// Move one in front:
_heap[0] = _heap.back(); _heap[0] = _heap.back();
_heap.pop_back(); _heap.pop_back();
it = _lookup.find(_heap[0].getKey()); it = _lookup.find(_heap[0].getKey());
@ -438,23 +441,29 @@ namespace triagens {
class Traverser { class Traverser {
friend class ::Searcher;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- data structures // --SECTION-- data structures
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- path // --SECTION-- types
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
public: public:
////////////////////////////////////////////////////////////////////////////////
/// @brief types for vertices, edges and weights
////////////////////////////////////////////////////////////////////////////////
typedef std::string VertexId; typedef std::string VertexId;
typedef std::string EdgeId; typedef std::string EdgeId;
typedef double EdgeWeight; typedef double EdgeWeight;
////////////////////////////////////////////////////////////////////////////////
/// @brief Path, type for the result
////////////////////////////////////////////////////////////////////////////////
// Convention vertices.size() -1 === edges.size() // Convention vertices.size() -1 === edges.size()
// path is vertices[0] , edges[0], vertices[1] etc. // path is vertices[0] , edges[0], vertices[1] etc.
struct Path { struct Path {
@ -462,29 +471,43 @@ namespace triagens {
std::deque<EdgeId> edges; std::deque<EdgeId> edges;
EdgeWeight weight; EdgeWeight weight;
Path ( Path (std::deque<VertexId> vertices, std::deque<EdgeId> edges,
std::deque<VertexId> vertices, EdgeWeight weight)
std::deque<EdgeId> edges, : vertices(vertices), edges(edges), weight(weight) {
EdgeWeight weight
) : vertices(vertices),
edges(edges),
weight(weight) {
}; };
}; };
struct Neighbor { ////////////////////////////////////////////////////////////////////////////////
VertexId neighbor; /// @brief Step, one position with a predecessor and the edge
EdgeId edge; ////////////////////////////////////////////////////////////////////////////////
EdgeWeight weight;
Neighbor ( struct Step {
VertexId neighbor, VertexId _vertex;
EdgeId edge, VertexId _predecessor;
EdgeWeight weight EdgeWeight _weight;
) : neighbor(neighbor), EdgeId _edge;
edge(edge), bool _done;
weight(weight) {
}; Step () : _done(false) {
}
Step (VertexId const& vert, VertexId const& pred,
EdgeWeight weig, EdgeId const& edge)
: _vertex(vert), _predecessor(pred), _weight(weig), _edge(edge),
_done(false) {
}
EdgeWeight weight () const {
return _weight;
}
void setWeight (EdgeWeight w) {
_weight = w;
}
VertexId const& getKey () const {
return _vertex;
}
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -493,7 +516,11 @@ namespace triagens {
typedef enum {FORWARD, BACKWARD} Direction; typedef enum {FORWARD, BACKWARD} Direction;
typedef std::function<void(VertexId source, std::vector<Neighbor>& result)> ////////////////////////////////////////////////////////////////////////////////
/// @brief callback to find neighbours
////////////////////////////////////////////////////////////////////////////////
typedef std::function<void(VertexId V, std::vector<Step>& result)>
ExpanderFunction; ExpanderFunction;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -504,12 +531,12 @@ namespace triagens {
/// @brief create the Traverser /// @brief create the Traverser
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Traverser ( Traverser (ExpanderFunction forwardExpander,
ExpanderFunction forwardExpander, ExpanderFunction backwardExpander)
ExpanderFunction backwardExpander : _highscoreSet(false),
) : highscore(1e50), _highscore(0),
bingo(false), _bingo(false),
intermediate(""), _intermediate(""),
_forwardExpander(forwardExpander), _forwardExpander(forwardExpander),
_backwardExpander(backwardExpander) { _backwardExpander(backwardExpander) {
}; };
@ -517,16 +544,14 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief destructor /// @brief destructor
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
~Traverser () { ~Traverser () {
// TODO: Implement!!
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public methods // --SECTION-- public methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
public:
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Find the shortest path between start and target. /// @brief Find the shortest path between start and target.
/// Only edges having the given direction are followed. /// Only edges having the given direction are followed.
@ -535,91 +560,59 @@ namespace triagens {
// Caller has to free the result // Caller has to free the result
// nullptr indicates there is no path // nullptr indicates there is no path
Path* ShortestPath ( Path* shortestPath (
VertexId const& start, VertexId const& start,
VertexId const& target VertexId const& target
); );
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private methods // --SECTION-- public data
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief Function to compute all neighbors of a given vertex /// @brief lowest total weight for a complete path found
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
private: bool _highscoreSet;
std::atomic<EdgeWeight> highscore; ////////////////////////////////////////////////////////////////////////////////
std::atomic<bool> bingo; /// @brief lowest total weight for a complete path found
std::mutex resultMutex; ////////////////////////////////////////////////////////////////////////////////
VertexId intermediate;
struct LookupInfo { EdgeWeight _highscore;
EdgeWeight weight;
bool done;
EdgeId edge;
VertexId predecessor;
LookupInfo ( ////////////////////////////////////////////////////////////////////////////////
EdgeWeight weight, /// @brief _bingo, flag that indicates termination
EdgeId edge, ////////////////////////////////////////////////////////////////////////////////
VertexId predecessor
) : weight(weight),
done(false),
edge(edge),
predecessor(predecessor) {
};
};
struct QueueInfo { std::atomic<bool> _bingo;
EdgeWeight weight;
VertexId vertex;
QueueInfo ( ////////////////////////////////////////////////////////////////////////////////
VertexId vertex, /// @brief _resultMutex, this is used to protect access to the result data
EdgeWeight weight ////////////////////////////////////////////////////////////////////////////////
) : weight(weight),
vertex(vertex) {
};
friend bool operator< (QueueInfo const& a, QueueInfo const& b) { std::mutex _resultMutex;
if (a.weight == b.weight) {
return a.vertex < b.vertex;
}
return a.weight < b.weight;
};
}; ////////////////////////////////////////////////////////////////////////////////
/// @brief _intermediate, one vertex on the shortest path found
////////////////////////////////////////////////////////////////////////////////
VertexId _intermediate;
// -----------------------------------------------------------------------------
// --SECTION-- private data
// -----------------------------------------------------------------------------
typedef triagens::basics::PriorityQueue<VertexId, Step, EdgeWeight>
PQueue;
// TODO: Destructor?!
struct ThreadInfo { struct ThreadInfo {
std::unordered_map<VertexId, LookupInfo>& lookup; PQueue _pq;
std::set<QueueInfo, std::less<QueueInfo>>& queue; std::mutex _mutex;
std::mutex& mutex;
ThreadInfo (
std::unordered_map<VertexId, LookupInfo>& lookup,
std::set<QueueInfo, std::less<QueueInfo>>& queue,
std::mutex& mutex
) : lookup(lookup),
queue(queue),
mutex(mutex) {
};
}; };
ExpanderFunction _forwardExpander; ExpanderFunction _forwardExpander;
ExpanderFunction _backwardExpander; ExpanderFunction _backwardExpander;
// ShortestPath will create these variables
std::unordered_map<VertexId, LookupInfo> _forwardLookup;
std::set<QueueInfo, std::less<QueueInfo>> _forwardQueue;
std::mutex _forwardMutex;
std::unordered_map<VertexId, LookupInfo> _backwardLookup;
std::set<QueueInfo, std::less<QueueInfo>> _backwardQueue;
std::mutex _backwardMutex;
}; };
} }
} }